In the article about section headers, you got an introduction to string tables. In this article, we will delve deeper into the topic.

…prologue

We’ll start with the same program we used in the previous article about section headers.

/* file: hello_world.c */

#include <stdio.h>

// A macro
#define HELLO_MSG1 "Hello World1"

// A global variable
char HELLO_MSG2[] = "Hello World2";


// main function
int main() {
    // local variable for main
    char HELLO_MSG3[] = "Hello World3";
    // Print messages
    printf("%s\n", HELLO_MSG1);
    printf("%s\n", HELLO_MSG2);
    printf("%s\n", HELLO_MSG3);
    return 0;
}

Compile this and then analyze the ELF executable file using readelf (Not everytime we’ll go with xxd).

❯ readelf --file-header --wide hello_world
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              DYN (Position-Independent Executable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x1050
  Start of program headers:          64 (bytes into file)
  Start of section headers:          13608 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         13
  Size of section headers:           64 (bytes)
  Number of section headers:         30
  Section header string table index: 29

With the help of this, you can get the section header table of the file.

#################### Explaination ###########################
#
# xxd \
#   -s <start_of_section_headers> \               # Start of section headers:   13608 (bytes into file)
#   -l <total_size_of_all_section_headers> \      # size_of_one_section_header(64) * total_count_of_section_headers(30)
#   -c <bytes_to_print_in_a_single_line>   \      # Just to get a section header entry in a single line
#   <ELF_file> \                                  #  ... duhh!
#   | nl -v0 -                                    # I wanted to get the line numbers starting from 0. WHY 0?? - because that's where the array indexing starts
#############################################################

❯ xxd \
    -s 13608 \
    -l $(( 64*30 )) \
    -c 64 \
    hello_world \
    | nl -v0 -


 0  00003528: 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000  ................................................................
 1  00003568: 1b00 0000 0100 0000 0200 0000 0000 0000 1803 0000 0000 0000 1803 0000 0000 0000 1c00 0000 0000 0000 0000 0000 0000 0000 0100 0000 0000 0000 0000 0000 0000 0000  ................................................................
 2  000035a8: 2300 0000 0700 0000 0200 0000 0000 0000 3803 0000 0000 0000 3803 0000 0000 0000 4000 0000 0000 0000 0000 0000 0000 0000 0800 0000 0000 0000 0000 0000 0000 0000  #...............8.......8.......@...............................
 3  000035e8: 3600 0000 0700 0000 0200 0000 0000 0000 7803 0000 0000 0000 7803 0000 0000 0000 2400 0000 0000 0000 0000 0000 0000 0000 0400 0000 0000 0000 0000 0000 0000 0000  6...............x.......x.......$...............................
 4  00003628: 4900 0000 0700 0000 0200 0000 0000 0000 9c03 0000 0000 0000 9c03 0000 0000 0000 2000 0000 0000 0000 0000 0000 0000 0000 0400 0000 0000 0000 0000 0000 0000 0000  I............................... ...............................
 5  00003668: 5700 0000 f6ff ff6f 0200 0000 0000 0000 c003 0000 0000 0000 c003 0000 0000 0000 1c00 0000 0000 0000 0600 0000 0000 0000 0800 0000 0000 0000 0000 0000 0000 0000  W......o........................................................
 6  000036a8: 6100 0000 0b00 0000 0200 0000 0000 0000 e003 0000 0000 0000 e003 0000 0000 0000 c000 0000 0000 0000 0700 0000 0100 0000 0800 0000 0000 0000 1800 0000 0000 0000  a...............................................................
 7  000036e8: 6900 0000 0300 0000 0200 0000 0000 0000 a004 0000 0000 0000 a004 0000 0000 0000 a800 0000 0000 0000 0000 0000 0000 0000 0100 0000 0000 0000 0000 0000 0000 0000  i...............................................................
 8  00003728: 7100 0000 ffff ff6f 0200 0000 0000 0000 4805 0000 0000 0000 4805 0000 0000 0000 1000 0000 0000 0000 0600 0000 0000 0000 0200 0000 0000 0000 0200 0000 0000 0000  q......o........H.......H.......................................
 9  00003768: 7e00 0000 feff ff6f 0200 0000 0000 0000 5805 0000 0000 0000 5805 0000 0000 0000 4000 0000 0000 0000 0700 0000 0100 0000 0800 0000 0000 0000 0000 0000 0000 0000  ~......o........X.......X.......@...............................
10  000037a8: 8d00 0000 0400 0000 0200 0000 0000 0000 9805 0000 0000 0000 9805 0000 0000 0000 c000 0000 0000 0000 0600 0000 0000 0000 0800 0000 0000 0000 1800 0000 0000 0000  ................................................................
11  000037e8: 9700 0000 0400 0000 4200 0000 0000 0000 5806 0000 0000 0000 5806 0000 0000 0000 3000 0000 0000 0000 0600 0000 1700 0000 0800 0000 0000 0000 1800 0000 0000 0000  ........B.......X.......X.......0...............................
12  00003828: a100 0000 0100 0000 0600 0000 0000 0000 0010 0000 0000 0000 0010 0000 0000 0000 1b00 0000 0000 0000 0000 0000 0000 0000 0400 0000 0000 0000 0000 0000 0000 0000  ................................................................
13  00003868: 9c00 0000 0100 0000 0600 0000 0000 0000 2010 0000 0000 0000 2010 0000 0000 0000 3000 0000 0000 0000 0000 0000 0000 0000 1000 0000 0000 0000 1000 0000 0000 0000  ................ ....... .......0...............................
14  000038a8: a700 0000 0100 0000 0600 0000 0000 0000 5010 0000 0000 0000 5010 0000 0000 0000 7101 0000 0000 0000 0000 0000 0000 0000 1000 0000 0000 0000 0000 0000 0000 0000  ................P.......P.......q...............................
15  000038e8: ad00 0000 0100 0000 0600 0000 0000 0000 c411 0000 0000 0000 c411 0000 0000 0000 0d00 0000 0000 0000 0000 0000 0000 0000 0400 0000 0000 0000 0000 0000 0000 0000  ................................................................
16  00003928: b300 0000 0100 0000 0200 0000 0000 0000 0020 0000 0000 0000 0020 0000 0000 0000 1100 0000 0000 0000 0000 0000 0000 0000 0400 0000 0000 0000 0000 0000 0000 0000  ................. ....... ......................................
17  00003968: bb00 0000 0100 0000 0200 0000 0000 0000 1420 0000 0000 0000 1420 0000 0000 0000 2400 0000 0000 0000 0000 0000 0000 0000 0400 0000 0000 0000 0000 0000 0000 0000  ................. ....... ......$...............................
18  000039a8: c900 0000 0100 0000 0200 0000 0000 0000 3820 0000 0000 0000 3820 0000 0000 0000 7c00 0000 0000 0000 0000 0000 0000 0000 0800 0000 0000 0000 0000 0000 0000 0000  ................8 ......8 ......|...............................
19  000039e8: d300 0000 0e00 0000 0300 0000 0000 0000 d03d 0000 0000 0000 d02d 0000 0000 0000 0800 0000 0000 0000 0000 0000 0000 0000 0800 0000 0000 0000 0800 0000 0000 0000  .................=.......-......................................
20  00003a28: df00 0000 0f00 0000 0300 0000 0000 0000 d83d 0000 0000 0000 d82d 0000 0000 0000 0800 0000 0000 0000 0000 0000 0000 0000 0800 0000 0000 0000 0800 0000 0000 0000  .................=.......-......................................
21  00003a68: eb00 0000 0600 0000 0300 0000 0000 0000 e03d 0000 0000 0000 e02d 0000 0000 0000 e001 0000 0000 0000 0700 0000 0000 0000 0800 0000 0000 0000 1000 0000 0000 0000  .................=.......-......................................
22  00003aa8: f400 0000 0100 0000 0300 0000 0000 0000 c03f 0000 0000 0000 c02f 0000 0000 0000 2800 0000 0000 0000 0000 0000 0000 0000 0800 0000 0000 0000 0800 0000 0000 0000  .................?......./......(...............................
23  00003ae8: f900 0000 0100 0000 0300 0000 0000 0000 e83f 0000 0000 0000 e82f 0000 0000 0000 2800 0000 0000 0000 0000 0000 0000 0000 0800 0000 0000 0000 0800 0000 0000 0000  .................?......./......(...............................
24  00003b28: 0201 0000 0100 0000 0300 0000 0000 0000 1040 0000 0000 0000 1030 0000 0000 0000 1d00 0000 0000 0000 0000 0000 0000 0000 0800 0000 0000 0000 0000 0000 0000 0000  .................@.......0......................................
25  00003b68: 0801 0000 0800 0000 0300 0000 0000 0000 2d40 0000 0000 0000 2d30 0000 0000 0000 0300 0000 0000 0000 0000 0000 0000 0000 0100 0000 0000 0000 0000 0000 0000 0000  ................-@......-0......................................
26  00003ba8: 0d01 0000 0100 0000 3000 0000 0000 0000 0000 0000 0000 0000 2d30 0000 0000 0000 1b00 0000 0000 0000 0000 0000 0000 0000 0100 0000 0000 0000 0100 0000 0000 0000  ........0...............-0......................................
27  00003be8: 0100 0000 0200 0000 0000 0000 0000 0000 0000 0000 0000 0000 4830 0000 0000 0000 7002 0000 0000 0000 1c00 0000 0600 0000 0800 0000 0000 0000 1800 0000 0000 0000  ........................H0......p...............................
28  00003c28: 0900 0000 0300 0000 0000 0000 0000 0000 0000 0000 0000 0000 b832 0000 0000 0000 5301 0000 0000 0000 0000 0000 0000 0000 0100 0000 0000 0000 0000 0000 0000 0000  .........................2......S...............................
29  00003c68: 1100 0000 0300 0000 0000 0000 0000 0000 0000 0000 0000 0000 0b34 0000 0000 0000 1601 0000 0000 0000 0000 0000 0000 0000 0100 0000 0000 0000 0000 0000 0000 0000  .........................4......................................

Now look back at the readelf output for this line

Section header string table index: 29

This gives the index for the string table which contains the names of all of the sections… Remember, sh_name member of section headers did not contained the actual name for the section but a index to section table. This is that section table.

On further analyzing this section table entry, we can identify everything about this section.

index |  offset   |  sh_name  |  sh_type  |        sh_flags     |        sh_addr      |       sh_offset     |       sh_size       |  sh_link  |  sh_info  |     sh_addralign    |       sh_entsize    |
29    | 00003c68: | 1100 0000 | 0300 0000 | 0000 0000 0000 0000 | 0000 0000 0000 0000 | 0b34 0000 0000 0000 | 1601 0000 0000 0000 | 0000 0000 | 0000 0000 | 0100 0000 0000 0000 | 0000 0000 0000 0000 |

Right now, interesting thing for us is the data that resides in this section. To get that, we need sh_offset and sh_size. (Keep in mind that these values are in little endian form)

❯ xxd \
    -s 0x340b \     # short for 0x000000000000340b (sh_offset)
    -l 0x116 \      # short for 0x0000000000000116 (sh_size)
    hello_world


0000340b: 002e 7379 6d74 6162 002e 7374 7274 6162  ..symtab..strtab
0000341b: 002e 7368 7374 7274 6162 002e 696e 7465  ..shstrtab..inte
0000342b: 7270 002e 6e6f 7465 2e67 6e75 2e70 726f  rp..note.gnu.pro
0000343b: 7065 7274 7900 2e6e 6f74 652e 676e 752e  perty..note.gnu.
0000344b: 6275 696c 642d 6964 002e 6e6f 7465 2e41  build-id..note.A
0000345b: 4249 2d74 6167 002e 676e 752e 6861 7368  BI-tag..gnu.hash
0000346b: 002e 6479 6e73 796d 002e 6479 6e73 7472  ..dynsym..dynstr
0000347b: 002e 676e 752e 7665 7273 696f 6e00 2e67  ..gnu.version..g
0000348b: 6e75 2e76 6572 7369 6f6e 5f72 002e 7265  nu.version_r..re
0000349b: 6c61 2e64 796e 002e 7265 6c61 2e70 6c74  la.dyn..rela.plt
000034ab: 002e 696e 6974 002e 7465 7874 002e 6669  ..init..text..fi
000034bb: 6e69 002e 726f 6461 7461 002e 6568 5f66  ni..rodata..eh_f
000034cb: 7261 6d65 5f68 6472 002e 6568 5f66 7261  rame_hdr..eh_fra
000034db: 6d65 002e 696e 6974 5f61 7272 6179 002e  me..init_array..
000034eb: 6669 6e69 5f61 7272 6179 002e 6479 6e61  fini_array..dyna
000034fb: 6d69 6300 2e67 6f74 002e 676f 742e 706c  mic..got..got.pl
0000350b: 7400 2e64 6174 6100 2e62 7373 002e 636f  t..data..bss..co
0000351b: 6d6d 656e 7400                           mment.

ASCII representation of this section’s data chunk confirms that this must be the string table. (the one which contains the names of the sections). Now atleast we know how to walk through the headers and locate a string table section. This gives us a green signal to go deeper and learn more about string tables.

String table

So, here’s the deal: when you’ve got a bunch of characters, and you end them with a null character, that whole thing is what we call a “string.” (At least, that’s what I’ve learned, and I’m sticking with it for now.)

Now, when it comes to a string table, it’s pretty simple. It’s just a bunch of these strings all lined up, one after the other. The only twist is that the first string is always null (just a null char - \0 - a null string). Now you can put all that data in a section and create a section header for it with type - SHT_STRTAB(which is just 0x3 in fancy lingo). And voila, you’ve got yourself a proper string table, with a section header entry for it.

If you want to picture it, think of it like this - a string table is like a list of strings, where the first one is always an empty string.

## Every 00 is a null char (in hex)
# For  Section=.shstrtab (Offset: 0x348b, Size: 278 = 0x116 in hex)

❯ xxd -s 0x340b -l 278 hello

0000348b: 002e 7379 6d74 6162 002e 7374 7274 6162  ..symtab..strtab
0000349b: 002e 7368 7374 7274 6162 002e 696e 7465  ..shstrtab..inte
000034ab: 7270 002e 6e6f 7465 2e67 6e75 2e70 726f  rp..note.gnu.pro
000034bb: 7065 7274 7900 2e6e 6f74 652e 676e 752e  perty..note.gnu.
000034cb: 6275 696c 642d 6964 002e 6e6f 7465 2e41  build-id..note.A
000034db: 4249 2d74 6167 002e 676e 752e 6861 7368  BI-tag..gnu.hash
000034eb: 002e 6479 6e73 796d 002e 6479 6e73 7472  ..dynsym..dynstr
000034fb: 002e 676e 752e 7665 7273 696f 6e00 2e67  ..gnu.version..g
0000350b: 6e75 2e76 6572 7369 6f6e 5f72 002e 7265  nu.version_r..re
0000351b: 6c61 2e64 796e 002e 7265 6c61 2e70 6c74  la.dyn..rela.plt
0000352b: 002e 696e 6974 002e 7465 7874 002e 6669  ..init..text..fi
0000353b: 6e69 002e 726f 6461 7461 002e 6568 5f66  ni..rodata..eh_f
0000354b: 7261 6d65 5f68 6472 002e 6568 5f66 7261  rame_hdr..eh_fra
0000355b: 6d65 002e 696e 6974 5f61 7272 6179 002e  me..init_array..
0000356b: 6669 6e69 5f61 7272 6179 002e 6479 6e61  fini_array..dyna
0000357b: 6d69 6300 2e67 6f74 002e 676f 742e 706c  mic..got..got.pl
0000358b: 7400 2e64 6174 6100 2e62 7373 002e 636f  t..data..bss..co
0000359b: 6d6d 656e 7400                           mment.

It should be pretty easy to write a parser for this, if not, ask your friend to do it for you. (hint: not me)

Now, to proceed, let’s take a look at the C program that I’ll be using for further examples

/*
file: hello.c
*/
#include <stdio.h>

int global1;
char global2 = 'x';
static int global3 = 9;

static void print_globals(void) {
    printf("global1 = %d (%p) | global2 = %c (%p) | global3 = %d (%p)\n",
        global1, &global1,
        global2, &global2,
        global3, &global3
    );
}

int main(){

    int local1;
    char local2 = 'y';
    static int local3 = 6;

    printf("Main: %p\n", &main);

    print_globals();

    printf("local1 = %d (%p) | local2 = %c (%p) | local3 = %d (%p)\n",
        local1, &local1,
        local2, &local2,
        local3, &local3
    );
    return 0;
}

I assume you can compile it and create the ELF binary. After the ELF binary is ready, analyze it to extract the list of all sections with a type of 0x3 (feeling fancy - SHT_STRTAB). Feel free to use readelf, hexdump, xxd, or any tool you prefer – the output should be same, regardless of your choice.

Using my pretty parser, I found three entries.

[ 07 ] Section Name: .dynstr        Type: 0x3       Flags: 0x2      Addr: 0x4a0     Offset: 0x4a0           Size: 170       Link: 0         Info: 0x0       Addralign: 0x1          Entsize: 0
[ 28 ] Section Name: .strtab        Type: 0x3       Flags: 0x0      Addr: 0x0       Offset: 0x3318          Size: 371       Link: 0         Info: 0x0       Addralign: 0x1          Entsize: 0
[ 29 ] Section Name: .shstrtab      Type: 0x3       Flags: 0x0      Addr: 0x0       Offset: 0x348b          Size: 278       Link: 0         Info: 0x0       Addralign: 0x1          Entsize: 0

Let’s examine them closely, one by one.

NOTE: String tables consist exclusively of strings. This data doesn’t serve much purpose unless those strings are needed by other sections.

1. .shstrtab

This is the string table (the one which stores the names of all of the sections) - well we already talked about it so no point of repeating it, right?

So, Why are the section names stored in a separate dedicated section, rather than directly within each section’s sh_name member??

Answer: While I can’t say for certain, it’s possible that this design choice was made to accommodate variable-length section names. Storing the names in a separate section allows flexibility in the length of section names and avoids any size constraints related to the sh_name member.

When I parse this with my parser, the data of this section appears like this – an offset in the section and the string stored at that offset.

[ 29 ] Section Name: .shstrtab      Type: 0x3       Flags: 0x0      Addr: 0x0       Offset: 0x348b          Size: 278       Link: 0         Info: 0x0       Addralign: 0x1          Entsize: 0
     [    0 ]
     [    1 ] .symtab
     [    9 ] .strtab
     [   17 ] .shstrtab
     [   27 ] .interp
     [   35 ] .note.gnu.property
     [   54 ] .note.gnu.build-id
     [   73 ] .note.ABI-tag
     [   87 ] .gnu.hash
     [   97 ] .dynsym
     [  105 ] .dynstr
     [  113 ] .gnu.version
     [  126 ] .gnu.version_r
     [  141 ] .rela.dyn
     [  151 ] .rela.plt
     [  161 ] .init
     [  167 ] .text
     [  173 ] .fini
     [  179 ] .rodata
     [  187 ] .eh_frame_hdr
     [  201 ] .eh_frame
     [  211 ] .init_array
     [  223 ] .fini_array
     [  235 ] .dynamic
     [  244 ] .got
     [  249 ] .got.plt
     [  258 ] .data
     [  264 ] .bss
     [  269 ] .comment

2. .strtab

This section contains strings (:P), mostly the ones representing names linked to symbol table entries (we’ll talk about symbol tables later). But at a quick glance, you can spot some of the names for variables and functions we used in our C program, such as global3, print_globals, main and so on.

Keep in mind that this section does not hold strings which are used by programs like the ones used with printf function.

[ 28 ] Section Name: .strtab        Type: 0x3       Flags: 0x0      Addr: 0x0       Offset: 0x3318          Size: 371       Link: 0         Info: 0x0       Addralign: 0x1          Entsize: 0
     [    0 ]
     [    1 ] hello.c
     [    9 ] global3
     [   17 ] print_globals
     [   31 ] local3.0
     [   40 ] _DYNAMIC
     [   49 ] __GNU_EH_FRAME_HDR
     [   68 ] _GLOBAL_OFFSET_TABLE_
     [   90 ] __libc_start_main@GLIBC_2.34
     [  119 ] _ITM_deregisterTMCloneTable
     [  147 ] _edata
     [  154 ] _fini
     [  160 ] __stack_chk_fail@GLIBC_2.4
     [  187 ] printf@GLIBC_2.2.5
     [  206 ] global1
     [  214 ] __data_start
     [  227 ] __gmon_start__
     [  242 ] __dso_handle
     [  255 ] _IO_stdin_used
     [  270 ] _end
     [  275 ] __bss_start
     [  287 ] main
     [  292 ] __TMC_END__
     [  304 ] _ITM_registerTMCloneTable
     [  330 ] __cxa_finalize@GLIBC_2.2.5
     [  357 ] _init
     [  363 ] global2

3. .dynstr

Similar to strtab, this section contains strings for symbol table entries, but these symbols come into play during runtime, often as part of dynamic linking. Because this section is used for dynamic linking, this needs to be loaded into memory for runtime use. You can confirm that with the sh_flags value for this section (should be 0x2 (or fancy, SHF_ALLOC))

For your satisfaction, here is the the output of readelf --segments hello, which indicates that this section is a part of the first LOAD segment

❯ readelf --segments --wide hello

Elf file type is DYN (Position-Independent Executable file)
Entry point 0x1050
There are 13 program headers, starting at offset 64

Program Headers:
  Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align
  0 PHDR           0x000040 0x0000000000000040 0x0000000000000040 0x0002d8 0x0002d8 R   0x8
  1 INTERP         0x000318 0x0000000000000318 0x0000000000000318 0x00001c 0x00001c R   0x1
      [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
  2 LOAD           0x000000 0x0000000000000000 0x0000000000000000 0x000690 0x000690 R   0x1000
  3 LOAD           0x001000 0x0000000000001000 0x0000000000001000 0x00024d 0x00024d R E 0x1000
  4 LOAD           0x002000 0x0000000000002000 0x0000000000002000 0x000154 0x000154 R   0x1000
  5 LOAD           0x002dd0 0x0000000000003dd0 0x0000000000003dd0 0x00025c 0x000268 RW  0x1000
  6 DYNAMIC        0x002de0 0x0000000000003de0 0x0000000000003de0 0x0001e0 0x0001e0 RW  0x8
  7 NOTE           0x000338 0x0000000000000338 0x0000000000000338 0x000040 0x000040 R   0x8
  8 NOTE           0x000378 0x0000000000000378 0x0000000000000378 0x000044 0x000044 R   0x4
  9 GNU_PROPERTY   0x000338 0x0000000000000338 0x0000000000000338 0x000040 0x000040 R   0x8
 10 GNU_EH_FRAME   0x002088 0x0000000000002088 0x0000000000002088 0x00002c 0x00002c R   0x4
 11 GNU_STACK      0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW  0x10
 12 GNU_RELRO      0x002dd0 0x0000000000003dd0 0x0000000000003dd0 0x000230 0x000230 R   0x1

 Section to Segment mapping:
  Segment Sections...
   00
   01     .interp
   02     .interp .note.gnu.property .note.gnu.build-id .note.ABI-tag .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt
   03     .init .plt .text .fini
   04     .rodata .eh_frame_hdr .eh_frame
   05     .init_array .fini_array .dynamic .got .got.plt .data .bss
   06     .dynamic
   07     .note.gnu.property
   08     .note.gnu.build-id .note.ABI-tag
   09     .note.gnu.property
   10     .eh_frame_hdr
   11
   12     .init_array .fini_array .dynamic .got

But the section structure is still same as any other string table, so my cool parser parsed it.

 [ 07 ] Section Name: .dynstr       Type: 0x3       Flags: 0x2      Addr: 0x4a0     Offset: 0x4a0           Size: 170       Link: 0         Info: 0x0       Addralign: 0x1          Entsize: 0
     [    0 ]
     [    1 ] __cxa_finalize
     [   16 ] __libc_start_main
     [   34 ] __stack_chk_fail
     [   51 ] printf
     [   58 ] libc.so.6
     [   68 ] GLIBC_2.2.5
     [   80 ] GLIBC_2.4
     [   90 ] GLIBC_2.34
     [  101 ] _ITM_deregisterTMCloneTable
     [  129 ] __gmon_start__
     [  144 ] _ITM_registerTMCloneTable

Conclusion

string tables in ELF files serve as repositories for various strings for section names, symbol names, and other dynamic linking data. The separation of string data into dedicated sections like “strtab” and “dynstr” allows for flexibility in string length and ensures that these essential strings are readily available during program execution.

Before closing this, I want you to run strip command against the ELF binary used in this article… Whatever happens will raise some good new questions for you to dig deeper (Some of those questions will be answered as we go forward with this series)