danigargu/syms2elf

adding local types to ELF?

saidelike opened this issue · 2 comments

Hi,

ida-syms2elf supports exporting function names, label, etc. I was able to import the symbols in gdb which is really cool. Would it be possible to add local types as well? Eg in GDB, it is then possible to import them using "add-symbol-file", the same method I use to import function names, label, etc.

For example, if we have the following type:

// sample.h
struct sample {
  int i;
  struct sample *less;
  struct sample *more;
};

In GDB, we don't have the type by default:

(gdb) p (struct sample *)0x7fffffffd6b0
No struct type named sample.

After importing the file containing the local types, we would be able to print the structure elements:

(gdb) add-symbol-file sample.o 0
add symbol table from file "sample.o" at
    .text_addr = 0x0
(gdb) p (struct sample *)0x7fffffffd6b0
$1 = (struct sample *) 0x7fffffffd6b0
(gdb) p *$1
$2 = {i = 42, less = 0x7fffffffd6b0, more = 0x7fffffffd6b0}

Regards
saidelike

[1] http://stackoverflow.com/questions/7272558/can-we-define-a-new-data-type-in-a-gdb-session

Hi saidelike!

I'll study if exists any form to add local types in the .symtab section, and in in that case, try to export types from IDA and radare2, but I think it is not possible (https://refspecs.linuxbase.org/elf/gabi4+/ch4.symtab.html).

Many thanks for you issue! :)

Regards

Hi danigargu,

Thanks for the answer. I looked as well and as you said it is not in the .symtab but instead in the .debug_info.

As a reference, this is how I listed a specific type in an ELF using pahole [2]:

$ pahole libc.so -C pthread_internal_t
struct pthread_internal_t {
    struct pthread_internal_t * next;                /*     0     4 */
    struct pthread_internal_t * * pref;              /*     4     4 */
    pthread_attr_t             attr;                 /*     8    24 */
    pid_t                      kernel_id;            /*    32     4 */
    pthread_cond_t             join_cond;            /*    36     4 */
    int                        join_count;           /*    40     4 */
    void *                     return_value;         /*    44     4 */
    int                        intern;               /*    48     4 */
    __pthread_cleanup_t *      cleanup_stack;        /*    52     4 */
    void * *                   tls;                  /*    56     4 */

    /* size: 60, cachelines: 1, members: 10 */
    /* last cacheline: 60 bytes */
};

To list them all and save the result in a file, we can use the following command:

$ pahole libc.so > lib.txt

Alternatively, objdump can be used to parse the .debug_info section:

$ objdump --dwarf libc.so > libc_objdump.txt

We get something like that. I only show the 2 first members (next and pref) of the pthread_internal_t structure below:

 <1><309>: Abbrev Number: 9 (DW_TAG_structure_type)
    <30a>   DW_AT_name        : (indirect string, offset: 0x29e): pthread_internal_t
    <30e>   DW_AT_byte_size   : 60
    <30f>   DW_AT_decl_file   : 11
    <310>   DW_AT_decl_line   : 36
    <311>   DW_AT_sibling     : <0x3a2>
 <2><315>: Abbrev Number: 10 (DW_TAG_member)
    <316>   DW_AT_name        : (indirect string, offset: 0xd6): next
    <31a>   DW_AT_decl_file   : 11
    <31b>   DW_AT_decl_line   : 37
    <31c>   DW_AT_type        : <0x3a2>
    <320>   DW_AT_data_member_location: 2 byte block: 23 0  (DW_OP_plus_uconst: 0)
 <2><323>: Abbrev Number: 10 (DW_TAG_member)
    <324>   DW_AT_name        : (indirect string, offset: 0x17d): pref
    <328>   DW_AT_decl_file   : 11
    <329>   DW_AT_decl_line   : 38
    <32a>   DW_AT_type        : <0x3a8>
    <32e>   DW_AT_data_member_location: 2 byte block: 23 4  (DW_OP_plus_uconst: 4)
...

I honestly don't know if the ELF parser you used (based on ROPgadget) supports parsing the .debug_info section but I wanted to share what I found in case you find it interesting and want to look further.

[2] http://stackoverflow.com/questions/5954140/dumping-c-structure-sizes-from-elf-object-file