konrad-kruczynski / elfsharp

Pure managed C# library for reading ELF, UImage, Mach-O binaries.
https://elfsharp.it
Other
159 stars 57 forks source link

Fix parsing error for loading Mach-O object file #78

Closed yongyan-gh closed 3 years ago

yongyan-gh commented 3 years ago

Fix InvalidOperation error when parsing a Mach-O object file. Fix for #77

According to this article:

For compactness, an intermediate object file contains only one segment. This segment has no name; it contains all the sections destined ultimately for different segments in the final object file. The data structure that defines a section contains the name of the segment the section is intended for, and the static linker places each section in the final object file accordingly.

For Mach-O object file I can see the only 1 segment name is empty and section names are set.

                SegName: __TEXT  | SecName: __text | Address: 0 | Size: 27 | Offset: 458 | Align: 0
                SegName: __TEXT  | SecName: __cstring | Address: 27 | Size: 1d | Offset: 47f | Align: 0
                SegName: __DWARF | SecName: __debug_frame | Address: 48 | Size: 48 | Offset: 4a0 | Align: 3
                SegName: __TEXT  | SecName: __eh_frame | Address: 90 | Size: 50 | Offset: 4e8 | Align: 3
                SegName: __DWARF | SecName: __debug_info | Address: e0 | Size: 1a1 | Offset: 538 | Align: 0
                SegName: __DWARF | SecName: __debug_abbrev | Address: 281 | Size: 7f | Offset: 6d9 | Align: 0
                SegName: __DWARF | SecName: __debug_pubnames | Address: 300 | Size: 27 | Offset: 758 | Align: 0
                SegName: __DWARF | SecName: __debug_pubtypes | Address: 327 | Size: cb | Offset: 77f | Align: 0
                SegName: __DWARF | SecName: __debug_aranges | Address: 3f2 | Size: 30 | Offset: 84a | Align: 0
                SegName: __DWARF | SecName: __debug_line | Address: 422 | Size: a7 | Offset: 87a | Align: 0
                SegName: __DWARF | SecName: __debug_str | Address: 4c9 | Size: 0 | Offset: 921 | Align: 0

Since binary files are not allowed to be checked-in, attached the binary file here which is used by test I added. simple-mach-o-object.zip

konrad-kruczynski commented 3 years ago

Hi @yongyan-gh! Many thanks for your PR. I'll probably have a look at it on weekend. Maybe earlier, if some spare time shows up ;)

yongyan-gh commented 3 years ago

Thank you @konrad-kruczynski !

cc @eddynaka @michaelcfanning

yongyan-gh commented 3 years ago

Populated couple missing fields in Mach-O Section: reloff / nreloc / flags according to https://opensource.apple.com/source/cctools/cctools-870/include/mach-o/loader.h

struct section { /* for 32-bit architectures */
    char        sectname[16];   /* name of this section */
    char        segname[16];    /* segment this section goes in */
    uint32_t    addr;       /* memory address of this section */
    uint32_t    size;       /* size in bytes of this section */
    uint32_t    offset;     /* file offset of this section */
    uint32_t    align;      /* section alignment (power of 2) */
    uint32_t    reloff;     /* file offset of relocation entries */
    uint32_t    nreloc;     /* number of relocation entries */
    uint32_t    flags;      /* flags (section type and attributes)*/
    uint32_t    reserved1;  /* reserved (for offset or index) */
    uint32_t    reserved2;  /* reserved (for count or sizeof) */
};

struct section_64 { /* for 64-bit architectures */
    char        sectname[16];   /* name of this section */
    char        segname[16];    /* segment this section goes in */
    uint64_t    addr;       /* memory address of this section */
    uint64_t    size;       /* size in bytes of this section */
    uint32_t    offset;     /* file offset of this section */
    uint32_t    align;      /* section alignment (power of 2) */
    uint32_t    reloff;     /* file offset of relocation entries */
    uint32_t    nreloc;     /* number of relocation entries */
    uint32_t    flags;      /* flags (section type and attributes)*/
    uint32_t    reserved1;  /* reserved (for offset or index) */
    uint32_t    reserved2;  /* reserved (for count or sizeof) */
    uint32_t    reserved3;  /* reserved */
};
konrad-kruczynski commented 3 years ago

Looks fine, I'll merge it, then add the necessary test file and bump version.