diff --git a/bundled/libdwarf/dwarf_abbrev.h b/bundled/libdwarf/dwarf_abbrev.h index b8511e9..20af595 100644 --- a/bundled/libdwarf/dwarf_abbrev.h +++ b/bundled/libdwarf/dwarf_abbrev.h @@ -27,6 +27,13 @@ */ +#ifndef DWARF_ABBREV_H +#define DWARF_ABBREV_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + /* In a given CU, one of these is (eventually) set up for every abbreviation we need to find (and for all those earlier in the abbreviations for that CU). @@ -67,3 +74,9 @@ int _dwarf_count_abbrev_entries(Dwarf_Debug dbg, Dwarf_Unsigned *abbrev_implicit_const_count_out, Dwarf_Byte_Ptr *abbrev_ptr_out, Dwarf_Error *error); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* DWARF_ABBREV_H */ diff --git a/bundled/libdwarf/dwarf_alloc.c b/bundled/libdwarf/dwarf_alloc.c index 6bb4c1e..cb5642f 100644 --- a/bundled/libdwarf/dwarf_alloc.c +++ b/bundled/libdwarf/dwarf_alloc.c @@ -1140,7 +1140,9 @@ _dwarf_free_all_of_one_debug(Dwarf_Debug dbg) /* de_alloc_tree might be NULL if global_de_alloc_tree_on is zero. */ if (dbg->de_alloc_tree) { + dbg->de_in_tdestroy = TRUE; dwarf_tdestroy(dbg->de_alloc_tree,tdestroy_free_node); + dbg->de_in_tdestroy = FALSE; dbg->de_alloc_tree = 0; } _dwarf_free_static_errlist(); diff --git a/bundled/libdwarf/dwarf_alloc.h b/bundled/libdwarf/dwarf_alloc.h index 6fb3b74..ac22cf5 100644 --- a/bundled/libdwarf/dwarf_alloc.h +++ b/bundled/libdwarf/dwarf_alloc.h @@ -26,6 +26,13 @@ Fifth Floor, Boston MA 02110-1301, USA. */ +#ifndef DWARF_ALLOC_H +#define DWARF_ALLOC_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + /* #define DWARF_SIMPLE_MALLOC 1 */ char * _dwarf_get_alloc(Dwarf_Debug, Dwarf_Small, Dwarf_Unsigned); @@ -43,3 +50,9 @@ void _dwarf_error_destructor(void *); void _dwarf_add_to_static_err_list(Dwarf_Error err); void _dwarf_flush_static_error_list(void); void _dwarf_free_static_errlist(void); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* DWARF_ALLOC_H */ diff --git a/bundled/libdwarf/dwarf_errmsg_list.h b/bundled/libdwarf/dwarf_errmsg_list.h index 1296612..41155ce 100644 --- a/bundled/libdwarf/dwarf_errmsg_list.h +++ b/bundled/libdwarf/dwarf_errmsg_list.h @@ -682,6 +682,8 @@ static const char _dwarf_errmsgs[DW_DLE_LAST+1][DW_MAX_MSG_LEN] = { {"DW_DLE_LINE_COUNT_WRONG(500) A count in a line table is " "not valid. Corrupt data."}, {"DW_DLE_ARITHMETIC_OVERFLOW(501) Arithmetic overflow. " - " Corrupt Dwarf." } + " Corrupt Dwarf." }, +{" DW_DLE_UNIVERSAL_BINARY_ERROR(502) Error reading Mach-O " + "uninversal binary head. Corrupt Mach-O object." } }; #endif /* DWARF_ERRMSG_LIST_H */ diff --git a/bundled/libdwarf/dwarf_frame.c b/bundled/libdwarf/dwarf_frame.c index 0cf00cd..5d5311c 100644 --- a/bundled/libdwarf/dwarf_frame.c +++ b/bundled/libdwarf/dwarf_frame.c @@ -2160,7 +2160,9 @@ dwarf_get_fde_for_die(Dwarf_Debug dbg, } /* DW_DLV_OK */ - /* This is the only situation this is set. */ + /* This is the only situation this is set. + and is really dangerous. as fde and cie + are set for dealloc by dwarf_finish(). */ new_fde->fd_fde_owns_cie = TRUE; /* Now read the cie corresponding to the fde, _dwarf_read_cie_fde_prefix checks @@ -3416,14 +3418,21 @@ _dwarf_frame_destructor(void *frame) struct Dwarf_Frame_s *fp = frame; _dwarf_free_fde_table(fp); } + void _dwarf_fde_destructor(void *f) { struct Dwarf_Fde_s *fde = f; + if (fde->fd_fde_owns_cie) { - /* This is just for dwarf_get_fde_for_die() */ - dwarf_dealloc(fde->fd_dbg,fde->fd_cie,DW_DLA_CIE); - fde->fd_cie = 0; + Dwarf_Debug dbg = fde->fd_dbg; + + if (!dbg->de_in_tdestroy) { + /* This is just for dwarf_get_fde_for_die() and + must not be applied in alloc tree destruction. */ + dwarf_dealloc(fde->fd_dbg,fde->fd_cie,DW_DLA_CIE); + fde->fd_cie = 0; + } } if (fde->fd_have_fde_tab) { _dwarf_free_fde_table(&fde->fd_fde_table); diff --git a/bundled/libdwarf/dwarf_frame2.c b/bundled/libdwarf/dwarf_frame2.c index 97cc955..83342ec 100644 --- a/bundled/libdwarf/dwarf_frame2.c +++ b/bundled/libdwarf/dwarf_frame2.c @@ -975,10 +975,12 @@ _dwarf_create_cie_from_after_start(Dwarf_Debug dbg, &gnu_personality_handler_addr, error); if (resz != DW_DLV_OK) { - _dwarf_error_string(dbg, error, - DW_DLE_FRAME_AUGMENTATION_UNKNOWN, - "DW_DLE_FRAME_AUGMENTATION_UNKNOWN " - " Reading gnu aug encodings failed"); + if (resz == DW_DLV_ERROR) { + _dwarf_error_string(dbg, error, + DW_DLE_FRAME_AUGMENTATION_UNKNOWN, + "DW_DLE_FRAME_AUGMENTATION_UNKNOWN " + " Reading gnu aug encodings failed"); + } /* DW_DLV_NO_ENTRY seems impossible. */ return resz; } frame_ptr += adlen; @@ -1119,7 +1121,7 @@ _dwarf_create_fde_from_after_start(Dwarf_Debug dbg, address_range in the FDE are read according to the CIE augmentation string instructions. */ - { + if (cieptr) { Dwarf_Small *fp_updated = 0; int res = _dwarf_read_encoded_ptr(dbg, section_pointer, @@ -1150,6 +1152,15 @@ _dwarf_create_fde_from_after_start(Dwarf_Debug dbg, return res; } frame_ptr = fp_updated; + } else { + _dwarf_error_string(dbg, error, + DW_DLE_AUG_DATA_LENGTH_BAD, + "DW_DLE_AUG_DATA_LENGTH_BAD: The " + "gcc augmentation cannot be read, " + "as no cie pointer is available " + "to get critical data, " + "Corrupt DWARF"); + return DW_DLV_ERROR; } { Dwarf_Unsigned adlen = 0; diff --git a/bundled/libdwarf/dwarf_generic_init.c b/bundled/libdwarf/dwarf_generic_init.c index a692d9b..6b905c1 100644 --- a/bundled/libdwarf/dwarf_generic_init.c +++ b/bundled/libdwarf/dwarf_generic_init.c @@ -125,6 +125,24 @@ set_global_paths_init(Dwarf_Debug dbg, Dwarf_Error* error) } /* New in December 2018. */ +int dwarf_init_path_a(const char *path, + char * true_path_out_buffer, + unsigned true_path_bufferlen, + unsigned groupnumber, + unsigned universalnumber, + Dwarf_Handler errhand, + Dwarf_Ptr errarg, + Dwarf_Debug * ret_dbg, + Dwarf_Error * error) +{ + return dwarf_init_path_dl_a(path, + true_path_out_buffer,true_path_bufferlen, + groupnumber,universalnumber, + errhand,errarg,ret_dbg, + 0,0,0, + error); +} + int dwarf_init_path(const char *path, char * true_path_out_buffer, unsigned true_path_bufferlen, @@ -134,9 +152,11 @@ int dwarf_init_path(const char *path, Dwarf_Debug * ret_dbg, Dwarf_Error * error) { - return dwarf_init_path_dl(path, + unsigned int universalnumber = 0; + return dwarf_init_path_dl_a(path, true_path_out_buffer,true_path_bufferlen, - groupnumber,errhand,errarg,ret_dbg, + groupnumber,universalnumber, + errhand,errarg,ret_dbg, 0,0,0, error); } @@ -192,6 +212,30 @@ dwarf_init_path_dl(const char *path, unsigned int dl_path_count, unsigned char * path_source, Dwarf_Error * error) +{ + unsigned int universalnumber = 0; + int res = 0; + + res = dwarf_init_path_dl_a(path, + true_path_out_buffer, true_path_bufferlen, + groupnumber,universalnumber, + errhand,errarg,ret_dbg, dl_path_array, + dl_path_count,path_source,error); + return res; +} +int +dwarf_init_path_dl_a(const char *path, + char * true_path_out_buffer, + unsigned true_path_bufferlen, + unsigned groupnumber, + unsigned universalnumber, + Dwarf_Handler errhand, + Dwarf_Ptr errarg, + Dwarf_Debug * ret_dbg, + char ** dl_path_array, + unsigned int dl_path_count, + unsigned char * path_source, + Dwarf_Error * error) { unsigned ftype = 0; unsigned endian = 0; @@ -302,9 +346,11 @@ dwarf_init_path_dl(const char *path, *ret_dbg = dbg; return res; } + case DW_FTYPE_APPLEUNIVERSAL: case DW_FTYPE_MACH_O: { res = _dwarf_macho_setup(fd, file_path, + universalnumber, ftype,endian,offsetsize,filesize, groupnumber,errhand,errarg,&dbg,error); if (res != DW_DLV_OK) { @@ -355,6 +401,7 @@ dwarf_init_b(int fd, unsigned ftype = 0; unsigned endian = 0; unsigned offsetsize = 0; + unsigned universalnumber = 0; Dwarf_Unsigned filesize = 0; int res = 0; int errcode = 0; @@ -387,10 +434,12 @@ dwarf_init_b(int fd, set_global_paths_init(*ret_dbg,error); return res2; } + case DW_FTYPE_APPLEUNIVERSAL: case DW_FTYPE_MACH_O: { int resm = 0; resm = _dwarf_macho_setup(fd,"", + universalnumber, ftype,endian,offsetsize,filesize, group_number,errhand,errarg,ret_dbg,error); if (resm != DW_DLV_OK) { diff --git a/bundled/libdwarf/dwarf_macho_loader.h b/bundled/libdwarf/dwarf_macho_loader.h index 5d7b85f..be16a99 100644 --- a/bundled/libdwarf/dwarf_macho_loader.h +++ b/bundled/libdwarf/dwarf_macho_loader.h @@ -76,6 +76,35 @@ extern "C" { #define TYP(n,l) char (n)[(l)] #endif /* TYP */ +/* This is Apple internal naming for Universal Binaries + and is not 'Inclusive Terminology" !! */ +#define FAT_MAGIC 0xcafebabe +#define FAT_CIGAM 0xbebafeca +#define FAT_MAGIC_64 0xcafebabf +#define FAT_CIGAM_64 0xbfbafeca + +struct fat_header { + TYP(magic,4); /* FAT_MAGIC or FAT_MAGIC_64 */ + TYP(nfat_arch,4); /* number of structs that follow */ +}; + +struct fat_arch { + TYP(cputype ,4); /* cpu specifier (int) */ + TYP(cpusubtype,4); /* machine specifier (int) */ + TYP(offset,4); /* file offset to this object file */ + TYP(size,4); /* size of this object file */ + TYP(align,4); /* alignment as a power of 2 */ +}; + +struct fat_arch_64 { + TYP(cputype,4); /* cpu specifier (int) */ + TYP(cpusubtype,4); /* machine specifier (int) */ + TYP(offset,8); /* file offset to this object file */ + TYP(size,8); /* size of this object file */ + TYP(align,4); /* alignment as a power of 2 */ + TYP(reserved,4); /* reserved */ +}; + /* * The 32-bit mach header appears at the very * beginning of the object file for diff --git a/bundled/libdwarf/dwarf_machoread.c b/bundled/libdwarf/dwarf_machoread.c index 1d17c37..96051f5 100644 --- a/bundled/libdwarf/dwarf_machoread.c +++ b/bundled/libdwarf/dwarf_machoread.c @@ -75,6 +75,8 @@ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include /* close() */ #endif /* _WIN32 */ +#include /* debugging printf */ + #include "dwarf.h" #include "libdwarf.h" #include "libdwarf_private.h" @@ -85,10 +87,26 @@ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "dwarf_reading.h" #include "dwarf_memcpy_swap.h" #include "dwarf_object_read_common.h" +#include "dwarf_universal.h" #include "dwarf_machoread.h" #include "dwarf_object_detector.h" #include "dwarf_macho_loader.h" +#if 0 +static void +dump_bytes(const char *msg,Dwarf_Small * start, long len) +{ + Dwarf_Small *end = start + len; + Dwarf_Small *cur = start; + printf("%s (0x%lx) ",msg,(unsigned long)start); + for (; cur < end; cur++) { + printf("%02x", *cur); + } + printf("\n"); +} +#endif /*0*/ + + /* MACH-O and dwarf section names */ static struct macho_sect_names_s { char const *ms_moname; @@ -111,12 +129,21 @@ static struct macho_sect_names_s { }; static int -_dwarf_macho_object_access_init( +_dwarf_object_detector_universal_head_fd( + int fd, + Dwarf_Unsigned dw_filesize, + unsigned int *dw_contentcount, + Dwarf_Universal_Head * dw_head, + int *errcode); + +static int _dwarf_macho_object_access_init( int fd, + unsigned uninumber, unsigned ftype, unsigned endian, unsigned offsetsize, - size_t filesize, + unsigned * universalbinary_count, + Dwarf_Unsigned filesize, Dwarf_Obj_Access_Interface_a **binary_interface, int *localerrnum); @@ -192,6 +219,7 @@ macho_load_section (void *obj, Dwarf_Unsigned section_index, if (0 < section_index && section_index < macho->mo_dwarf_sectioncount) { int res = 0; + Dwarf_Unsigned inner = macho->mo_inner_offset; struct generic_macho_section *sp = macho->mo_dwarf_sections + section_index; @@ -214,8 +242,9 @@ macho_load_section (void *obj, Dwarf_Unsigned section_index, return DW_DLV_ERROR; } res = RRMOA(macho->mo_fd, - sp->loaded_data, (off_t)sp->offset, - (size_t)sp->size, (off_t)macho->mo_filesize, error); + sp->loaded_data, (off_t)(inner+sp->offset), + (size_t)sp->size, + (off_t)(inner+macho->mo_filesize), error); if (res != DW_DLV_OK) { free(sp->loaded_data); sp->loaded_data = 0; @@ -276,13 +305,14 @@ load_macho_header32(dwarf_macho_object_access_internals_t *mfp, { struct mach_header mh32; int res = 0; + Dwarf_Unsigned inner = mfp->mo_inner_offset; if (sizeof(mh32) > mfp->mo_filesize) { *errcode = DW_DLE_FILE_TOO_SMALL; return DW_DLV_ERROR; } - res = RRMOA(mfp->mo_fd, &mh32, 0, sizeof(mh32), - (off_t)mfp->mo_filesize, errcode); + res = RRMOA(mfp->mo_fd, &mh32, inner, sizeof(mh32), + (off_t)(inner+mfp->mo_filesize), errcode); if (res != DW_DLV_OK) { return res; } @@ -316,13 +346,14 @@ load_macho_header64(dwarf_macho_object_access_internals_t *mfp, { struct mach_header_64 mh64; int res = 0; + Dwarf_Unsigned inner = mfp->mo_inner_offset; if (sizeof(mh64) > mfp->mo_filesize) { *errcode = DW_DLE_FILE_TOO_SMALL; return DW_DLV_ERROR; } - res = RRMOA(mfp->mo_fd, &mh64, 0, sizeof(mh64), - (off_t)mfp->mo_filesize, errcode); + res = RRMOA(mfp->mo_fd, &mh64, inner, sizeof(mh64), + (off_t)(inner+mfp->mo_filesize), errcode); if (res != DW_DLV_OK) { return res; } @@ -378,15 +409,16 @@ load_segment_command_content32( Dwarf_Unsigned filesize = mfp->mo_filesize; Dwarf_Unsigned segoffset = mmp->offset_this_command; Dwarf_Unsigned afterseghdr = segoffset + sizeof(sc); + Dwarf_Unsigned inner = mfp->mo_inner_offset; - if (mmp->offset_this_command > filesize || + if (segoffset > filesize || mmp->cmdsize > filesize || - (mmp->cmdsize + mmp->offset_this_command) > filesize ) { + (mmp->cmdsize + segoffset) > filesize ) { *errcode = DW_DLE_MACH_O_SEGOFFSET_BAD; return DW_DLV_ERROR; } - res = RRMOA(mfp->mo_fd, &sc, (off_t)mmp->offset_this_command, - sizeof(sc), (off_t)filesize, errcode); + res = RRMOA(mfp->mo_fd, &sc, (off_t)(inner+segoffset), + sizeof(sc), (off_t)(inner+filesize), errcode); if (res != DW_DLV_OK) { return res; } @@ -432,6 +464,8 @@ load_segment_command_content32( return DW_DLV_OK; } +void fuck() {} + static int load_segment_command_content64( dwarf_macho_object_access_internals_t *mfp, @@ -444,15 +478,17 @@ load_segment_command_content64( Dwarf_Unsigned filesize = mfp->mo_filesize; Dwarf_Unsigned segoffset = mmp->offset_this_command; Dwarf_Unsigned afterseghdr = segoffset + sizeof(sc); + Dwarf_Unsigned inner = mfp->mo_inner_offset; if (segoffset > filesize || mmp->cmdsize > filesize || (mmp->cmdsize + segoffset) > filesize ) { *errcode = DW_DLE_MACHO_CORRUPT_COMMAND; + fuck(); return DW_DLV_ERROR; } - res = RRMOA(mfp->mo_fd,&sc,segoffset, - sizeof(sc), (off_t)filesize, errcode); + res = RRMOA(mfp->mo_fd,&sc,inner+segoffset, + sizeof(sc), (off_t)(inner+filesize), errcode); if (res != DW_DLV_OK) { return res; } @@ -468,11 +504,13 @@ load_segment_command_content64( msp->filesize > filesize) { /* corrupt */ *errcode = DW_DLE_MACHO_CORRUPT_COMMAND; + fuck(); return DW_DLV_ERROR; } if ((msp->fileoff+msp->filesize ) > filesize) { /* corrupt */ *errcode = DW_DLE_MACHO_CORRUPT_COMMAND; + fuck(); return DW_DLV_ERROR; } ASNAR(mfp->mo_copy_word,msp->maxprot,sc.maxprot); @@ -489,9 +527,9 @@ load_segment_command_content64( (unsigned long)mfp->mo_filesize); #endif *errcode = DW_DLE_MACHO_CORRUPT_COMMAND; + fuck(); return DW_DLV_ERROR; } - ASNAR(mfp->mo_copy_word,msp->flags,sc.flags); msp->macho_command_index = mmpindex; msp->sectionsoffset = afterseghdr; @@ -580,6 +618,7 @@ _dwarf_macho_load_dwarf_section_details32( struct section mosec; int res = 0; Dwarf_Unsigned endoffset = 0; + Dwarf_Unsigned inner = mfp->mo_inner_offset; endoffset = curoff + sizeof(mosec); if (curoff >= mfp->mo_filesize || @@ -596,8 +635,8 @@ _dwarf_macho_load_dwarf_section_details32( *errcode = DW_DLE_MACHO_CORRUPT_SECTIONDETAILS; return DW_DLV_ERROR; } - res = RRMOA(mfp->mo_fd, &mosec, (off_t)curoff, sizeof(mosec), - (off_t)mfp->mo_filesize, errcode); + res = RRMOA(mfp->mo_fd, &mosec, (off_t)(inner+curoff), sizeof(mosec), + (off_t)(inner+mfp->mo_filesize), errcode); if (res != DW_DLV_OK) { return res; } @@ -667,8 +706,8 @@ _dwarf_macho_load_dwarf_section_details64( for (; seci < secalloc; ++seci,++secs,curoff += shdrlen ) { int res = 0; struct section_64 mosec; - Dwarf_Unsigned endoffset = 0; + Dwarf_Unsigned inner = mfp->mo_inner_offset; endoffset = curoff + sizeof(mosec); if (curoff >= mfp->mo_filesize || @@ -686,8 +725,9 @@ _dwarf_macho_load_dwarf_section_details64( return DW_DLV_ERROR; } - res = RRMOA(mfp->mo_fd, &mosec, (off_t)curoff, sizeof(mosec), - (off_t)mfp->mo_filesize, errcode); + res = RRMOA(mfp->mo_fd, &mosec, + (off_t)(inner+curoff), sizeof(mosec), + (off_t)(inner+mfp->mo_filesize), errcode); if (res != DW_DLV_OK) { return res; } @@ -773,6 +813,7 @@ _dwarf_load_macho_commands( struct generic_macho_command *mcp = 0; unsigned segment_command_count = 0; int res = 0; + Dwarf_Unsigned inner = mfp->mo_inner_offset; if (mfp->mo_command_count >= mfp->mo_filesize) { /* corrupt object. */ @@ -795,8 +836,9 @@ _dwarf_load_macho_commands( } mcp = mfp->mo_commands; for ( ; cmdi < mfp->mo_header.ncmds; ++cmdi,++mcp ) { - res = RRMOA(mfp->mo_fd, &mc, (off_t)curoff, sizeof(mc), - (off_t)mfp->mo_filesize, errcode); + res = RRMOA(mfp->mo_fd, &mc, + (off_t)(inner+curoff), sizeof(mc), + (off_t)(inner+mfp->mo_filesize), errcode); if (res != DW_DLV_OK) { return res; } @@ -825,10 +867,11 @@ _dwarf_load_macho_commands( int _dwarf_macho_setup(int fd, char *true_path, + unsigned universalnumber, unsigned ftype, unsigned endian, unsigned offsetsize, - size_t filesize, + Dwarf_Unsigned filesize, unsigned groupnumber, Dwarf_Handler errhand, Dwarf_Ptr errarg, @@ -838,10 +881,14 @@ _dwarf_macho_setup(int fd, dwarf_macho_object_access_internals_t *intfc = 0; int res = DW_DLV_OK; int localerrnum = 0; + unsigned universalbinary_count = 0; res = _dwarf_macho_object_access_init( fd, - ftype,endian,offsetsize,filesize, + universalnumber, + ftype,endian,offsetsize, + &universalbinary_count, + filesize, &binary_interface, &localerrnum); if (res != DW_DLV_OK) { @@ -861,6 +908,8 @@ _dwarf_macho_setup(int fd, } intfc = binary_interface->ai_object; intfc->mo_path = strdup(true_path); + (*dbg)->de_universalbinary_index = universalnumber; + (*dbg)->de_universalbinary_count = universalbinary_count; return res; } @@ -877,15 +926,86 @@ static Dwarf_Obj_Access_Methods_a const macho_methods = { NULL }; +/* Reads universal binary headers, gets to + the chosen inner binary, and returns the + values from the inner binary. + The filesize being that of the inner binary, + and the fileoffset being the offset of the inner + binary (so by definition > 0); +*/ + +static int +_dwarf_macho_inner_object_fd(int fd, + unsigned int uninumber, + Dwarf_Unsigned outer_filesize, + unsigned int *ftype, + unsigned int *unibinarycount, + unsigned int *endian, + unsigned int *offsetsize, + Dwarf_Unsigned *fileoffset, + Dwarf_Unsigned *filesize, + int *errcode) +{ + int res = 0; + Dwarf_Universal_Head head = 0; + Dwarf_Unsigned innerbase = 0; + Dwarf_Unsigned innersize = 0; + + res = _dwarf_object_detector_universal_head_fd( + fd, outer_filesize, unibinarycount, + &head, errcode); + if (res != DW_DLV_OK) { + return res; + } + if (uninumber >= *unibinarycount) { + *errcode = DW_DLE_UNIVERSAL_BINARY_ERROR; + _dwarf_dealloc_universal_head(head); + return DW_DLV_ERROR; + } + /* Now find the precise details of uninumber + instance we want */ + + innerbase = head->au_arches[uninumber].au_offset; + innersize = head->au_arches[uninumber].au_size; + if (innersize >= outer_filesize || + innerbase >= outer_filesize) { + *errcode = DW_DLE_UNIVERSAL_BINARY_ERROR; + _dwarf_dealloc_universal_head(head); + return DW_DLV_ERROR; + } + /* Now access inner to return its specs */ + { + /* But ignore the size this returns! + we determined that above. the following call + does not get the inner size, we got that + just above here! */ + Dwarf_Unsigned fake_size = 0; + + res = _dwarf_object_detector_fd_a(fd, + ftype,endian,offsetsize,innerbase,&fake_size, + errcode); + if (res != DW_DLV_OK) { + _dwarf_dealloc_universal_head(head); + return res; + } + } + *fileoffset = innerbase; + *filesize = innersize; + _dwarf_dealloc_universal_head(head); + return DW_DLV_OK; +} + /* On any error this frees internals argument. */ static int _dwarf_macho_object_access_internals_init( dwarf_macho_object_access_internals_t * internals, int fd, + unsigned uninumber, unsigned ftype, unsigned endian, unsigned offsetsize, - size_t filesize, + unsigned *unibinarycount, + Dwarf_Unsigned filesize, int *errcode) { dwarf_macho_object_access_internals_t * intfc = internals; @@ -893,6 +1013,12 @@ _dwarf_macho_object_access_internals_init( struct generic_macho_section *sp = 0; struct Dwarf_Obj_Access_Interface_a_s *localdoas; int res = 0; + unsigned int ftypei = ftype; + unsigned int endiani = endian; + unsigned int offsetsizei = offsetsize; + Dwarf_Unsigned filesizei = filesize; + Dwarf_Unsigned fileoffseti = 0; + unsigned int unibinarycounti = 0; /* Must malloc as _dwarf_destruct_macho_access() forces that due to other uses. */ @@ -903,15 +1029,34 @@ _dwarf_macho_object_access_internals_init( *errcode = DW_DLE_ALLOC_FAIL; return DW_DLV_ERROR; } - memset(localdoas,0,sizeof(struct Dwarf_Obj_Access_Interface_a_s)); + if (ftype == DW_FTYPE_APPLEUNIVERSAL) { + res = _dwarf_macho_inner_object_fd(fd, + uninumber, + filesize, + &ftypei,&unibinarycounti,&endiani, + &offsetsizei,&fileoffseti,&filesizei,errcode); + if (res != DW_DLV_OK) { + if (res == DW_DLV_ERROR) { + *errcode = DW_DLE_UNIVERSAL_BINARY_ERROR; + } + return res; + } + *unibinarycount = unibinarycounti; + endian = endiani; + } + + memset(localdoas,0, + sizeof(struct Dwarf_Obj_Access_Interface_a_s)); intfc->mo_ident[0] = 'M'; intfc->mo_ident[1] = '1'; intfc->mo_fd = fd; - intfc->mo_is_64bit = ((offsetsize==64)?TRUE:FALSE); - intfc->mo_offsetsize = offsetsize; - intfc->mo_pointersize = offsetsize; - intfc->mo_filesize = filesize; - intfc->mo_ftype = ftype; + intfc->mo_offsetsize = offsetsizei; + intfc->mo_pointersize = offsetsizei; + intfc->mo_inner_offset = fileoffseti; + intfc->mo_filesize = filesizei; + intfc->mo_ftype = ftypei; + intfc->mo_uninumber = uninumber; + intfc->mo_universal_count = unibinarycounti; #ifdef WORDS_BIGENDIAN if (endian == DW_END_little ) { @@ -974,10 +1119,12 @@ _dwarf_macho_object_access_internals_init( static int _dwarf_macho_object_access_init( int fd, + unsigned uninumber, unsigned ftype, unsigned endian, unsigned offsetsize, - size_t filesize, + unsigned * universalbinary_count, + Dwarf_Unsigned filesize, Dwarf_Obj_Access_Interface_a **binary_interface, int *localerrnum) { @@ -986,7 +1133,8 @@ _dwarf_macho_object_access_init( dwarf_macho_object_access_internals_t *internals = 0; Dwarf_Obj_Access_Interface_a *intfc = 0; - internals = malloc(sizeof(dwarf_macho_object_access_internals_t)); + internals = malloc( + sizeof(dwarf_macho_object_access_internals_t)); if (!internals) { *localerrnum = DW_DLE_ALLOC_FAIL; /* Impossible case, we hope. Give up. */ @@ -995,7 +1143,10 @@ _dwarf_macho_object_access_init( memset(internals,0,sizeof(*internals)); res = _dwarf_macho_object_access_internals_init(internals, fd, - ftype, endian, offsetsize, filesize, + uninumber, + ftype, endian, offsetsize, + universalbinary_count, + filesize, localerrnum); if (res != DW_DLV_OK){ /* *err is already set and the call freed internals. */ @@ -1015,3 +1166,267 @@ _dwarf_macho_object_access_init( *binary_interface = intfc; return DW_DLV_OK; } + +static unsigned long +magic_copy(unsigned char *d, unsigned len) +{ + unsigned i = 0; + unsigned long v = 0; + + v = d[0]; + for (i = 1 ; i < len; ++i) { + v <<= 8; + v |= d[i]; + } + return v; +} + +static int +fill_in_uni_arch_32( + struct fat_arch * fa, + struct Dwarf_Universal_Head_s *duhd, + void (*word_swap) (void *, const void *, size_t)) +{ + Dwarf_Unsigned i = 0; + struct Dwarf_Universal_Arch_s * dua = 0; + + dua = duhd->au_arches; + for ( ; i < duhd->au_count; ++i,++fa,++dua) { + ASNAR(word_swap,dua->au_cputype,fa->cputype); + ASNAR(word_swap,dua->au_cpusubtype,fa->cpusubtype); + ASNAR(word_swap,dua->au_offset,fa->offset); + ASNAR(word_swap,dua->au_size,fa->size); + ASNAR(word_swap,dua->au_align,fa->align); + dua->au_reserved = 0; + } + return DW_DLV_OK; +} + +static int +fill_in_uni_arch_64( + struct fat_arch_64 * fa, + struct Dwarf_Universal_Head_s *duhd, + void (*word_swap) (void *, const void *, size_t)) +{ + Dwarf_Unsigned i = 0; + struct Dwarf_Universal_Arch_s * dua = 0; + + dua = duhd->au_arches; + for ( ; i < duhd->au_count; ++i,++fa,++dua) { + ASNAR(word_swap,dua->au_cputype,fa->cputype); + ASNAR(word_swap,dua->au_cpusubtype,fa->cpusubtype); + ASNAR(word_swap,dua->au_offset,fa->offset); + ASNAR(word_swap,dua->au_size,fa->size); + ASNAR(word_swap,dua->au_align,fa->align); + ASNAR(word_swap,dua->au_align,fa->align); + ASNAR(word_swap,dua->au_reserved,fa->reserved); + } + return DW_DLV_OK; +} + +static const struct Dwarf_Universal_Head_s duhzero; +static const struct fat_header fhzero; +static int +_dwarf_object_detector_universal_head_fd( + int fd, + Dwarf_Unsigned dw_filesize, + unsigned int *dw_contentcount, + Dwarf_Universal_Head * dw_head, + int *errcode) +{ + struct Dwarf_Universal_Head_s duhd; + struct Dwarf_Universal_Head_s *duhdp = 0; + struct fat_header fh; + int res = 0; + void (*word_swap) (void *, const void *, size_t); + int locendian = 0; + int locoffsetsize = 0; + + duhd = duhzero; + fh = fhzero; + /* A universal head is always at offset zero. */ + res = RRMOA(fd,&fh,0,sizeof(fh), dw_filesize,errcode); + if (res != DW_DLV_OK) { + printf("Reading struct for universal binary " + "header failed\n"); + return res; + } + duhd.au_magic = magic_copy((unsigned char *)&fh.magic[0],4); + if (duhd.au_magic == FAT_MAGIC) { + locendian = DW_END_big; + locoffsetsize = 32; + } else if (duhd.au_magic == FAT_CIGAM) { + locendian = DW_END_little; + locoffsetsize = 32; + }else if (duhd.au_magic == FAT_MAGIC_64) { + locendian = DW_END_big; + locoffsetsize = 64; + } else if (duhd.au_magic == FAT_CIGAM_64) { + locendian = DW_END_little; + locoffsetsize = 64; + } else { +printf("Reading magic number universal compare failed " "Inconsistent\n"); + *errcode = DW_DLE_FILE_WRONG_TYPE; + return DW_DLV_ERROR; + } +#ifdef WORDS_BIGENDIAN + if (locendian == DW_END_little) { + word_swap = _dwarf_memcpy_swap_bytes; + } else { + word_swap = _dwarf_memcpy_noswap_bytes; + } +#else /* LITTLE ENDIAN */ + if (locendian == DW_END_little) { + word_swap = _dwarf_memcpy_noswap_bytes; + } else { + word_swap = _dwarf_memcpy_swap_bytes; + } +#endif /* LITTLE- BIG-ENDIAN */ + + ASNAR(word_swap,duhd.au_count,fh.nfat_arch); + /* The limit is a first-cut safe heuristic. */ + if (duhd.au_count >= (dw_filesize/2) ) { + *errcode = DW_DLE_UNIVERSAL_BINARY_ERROR ; + return DW_DLV_ERROR; + } + duhd.au_arches = (struct Dwarf_Universal_Arch_s*) + calloc(duhd.au_count, sizeof(struct Dwarf_Universal_Arch_s)); + if (!duhd.au_arches) { + *errcode = DW_DLE_ALLOC_FAIL; + return DW_DLV_ERROR; + } + if (locoffsetsize == 32) { + struct fat_arch * fa = 0; + fa = (struct fat_arch *)calloc(duhd.au_count, + sizeof(struct fat_arch)); + if (!fa) { + *errcode = DW_DLE_ALLOC_FAIL; + free(duhd.au_arches); + duhd.au_arches = 0; + free(fa); + return res; + } + res = RRMOA(fd,fa,/*offset=*/sizeof(fh), + duhd.au_count*sizeof(*fa), + dw_filesize,errcode); + if (res != DW_DLV_OK) { + free(duhd.au_arches); + duhd.au_arches = 0; + free(fa); + return res; + } + res = fill_in_uni_arch_32(fa,&duhd,word_swap); + if (res != DW_DLV_OK) { + free(duhd.au_arches); + duhd.au_arches = 0; + free(fa); + return res; + } + free(fa); + fa = 0; + } else { /* 64 */ + struct fat_arch_64 * fa = 0; + fa = (struct fat_arch_64 *)calloc(duhd.au_count, + sizeof(struct fat_arch)); + if (!fa) { + *errcode = DW_DLE_ALLOC_FAIL; + free(duhd.au_arches); + duhd.au_arches = 0; + return res; + } + res = RRMOA(fd,fa,/*offset*/sizeof(fh), + duhd.au_count*sizeof(fa), + dw_filesize,errcode); + if (res == DW_DLV_ERROR) { + free(duhd.au_arches); + duhd.au_arches = 0; + free(fa); + return res; + } + res = fill_in_uni_arch_64(fa,&duhd,word_swap); + if (res != DW_DLV_OK) { + free(duhd.au_arches); + duhd.au_arches = 0; + return res; + } + free(fa); + fa = 0; + } + + duhdp = malloc(sizeof(*duhdp)); + if (!duhdp) { + free(duhd.au_arches); + duhd.au_arches = 0; + *errcode = DW_DLE_ALLOC_FAIL; + return res; + } + memcpy(duhdp,&duhd,sizeof(duhd)); + *dw_contentcount = duhd.au_count; + duhdp->au_arches = duhd.au_arches; + *dw_head = duhdp; + return res; +} + +#if 0 +static void +print_arch_item(unsigned int i, + struct Dwarf_Universal_Arch_s* arch) +{ + printf(" Universal Binary Index " LONGESTUFMT "\n",i); + printf(" cpu " LONGESTXFMT "\n",arch->au_cputype); + printf(" cpusubt " LONGESTXFMT "\n",arch->au_cpusubtype); + printf(" offset " LONGESTXFMT "\n",arch->au_offset); + printf(" size " LONGESTXFMT "\n",arch->au_size); + printf(" align " LONGESTXFMT "\n",arch->au_align); +} +#endif + +int +_dwarf_object_detector_universal_instance( + Dwarf_Universal_Head dw_head, + Dwarf_Unsigned dw_index_of, + Dwarf_Unsigned *dw_cpu_type, + Dwarf_Unsigned *dw_cpusubtype, + Dwarf_Unsigned *dw_offset, + Dwarf_Unsigned *dw_size, + Dwarf_Unsigned *dw_align, + int *errcode) +{ + struct Dwarf_Universal_Arch_s* arch = 0; + + if (!dw_head) { + printf("Missing argument to " + "dwarf_object_detector_universal_instance"); + *errcode = DW_DLE_UNIVERSAL_BINARY_ERROR; + return DW_DLV_ERROR; + } + if (dw_index_of >= dw_head->au_count){ +printf("Requested index 0x%lu" +" to specific binary " +"is too larg: valid: 0 to 0x%lu\n", +(unsigned long)dw_index_of, +(unsigned long)dw_head->au_count); + return DW_DLV_NO_ENTRY; + } + arch = dw_head->au_arches +dw_index_of; + *dw_cpu_type = arch->au_cputype; + *dw_cpusubtype = arch->au_cpusubtype; + *dw_offset = arch->au_offset; + *dw_size = arch->au_size; + *dw_align = arch->au_align; +#if 0 + print_arch_item(dw_index_of,arch); +#endif + return DW_DLV_OK; +} + +void +_dwarf_dealloc_universal_head(Dwarf_Universal_Head dw_head) +{ + if (!dw_head) { + return; + } + free(dw_head->au_arches); + dw_head->au_arches = 0; + free(dw_head); +} diff --git a/bundled/libdwarf/dwarf_machoread.h b/bundled/libdwarf/dwarf_machoread.h index f5e6809..d556cbb 100644 --- a/bundled/libdwarf/dwarf_machoread.h +++ b/bundled/libdwarf/dwarf_machoread.h @@ -33,6 +33,22 @@ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef DWARF_MACHOREAD_H #define DWARF_MACHOREAD_H +struct Dwarf_Universal_Arch_s; +struct Dwarf_Universal_Head_s { + Dwarf_Unsigned au_magic; + Dwarf_Unsigned au_count; + struct Dwarf_Universal_Arch_s * au_arches; + +}; +struct Dwarf_Universal_Arch_s { + Dwarf_Unsigned au_cputype; + Dwarf_Unsigned au_cpusubtype; + Dwarf_Unsigned au_offset; + Dwarf_Unsigned au_size; + Dwarf_Unsigned au_align; + Dwarf_Unsigned au_reserved; +}; + #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ @@ -102,12 +118,14 @@ typedef struct dwarf_macho_filedata_s { const char * mo_path; /* libdwarf must free.*/ int mo_fd; int mo_destruct_close_fd; /*aka: lib owns fd */ - int mo_is_64bit; Dwarf_Unsigned mo_filesize; + Dwarf_Unsigned mo_inner_offset; /* for universal inner */ Dwarf_Small mo_offsetsize; /* 32 or 64 section data */ Dwarf_Small mo_pointersize; int mo_ftype; Dwarf_Small mo_endian; + unsigned mo_uninumber; /* for universal binary */ + unsigned mo_universal_count; /* for universal binary*/ /*Dwarf_Small mo_machine; */ void (*mo_copy_word) (void *, const void *, unsigned long); diff --git a/bundled/libdwarf/dwarf_object_detector.c b/bundled/libdwarf/dwarf_object_detector.c index a3d12b9..793a7e1 100644 --- a/bundled/libdwarf/dwarf_object_detector.c +++ b/bundled/libdwarf/dwarf_object_detector.c @@ -56,6 +56,7 @@ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "dwarf_memcpy_swap.h" #include "dwarf_object_read_common.h" #include "dwarf_object_detector.h" +#include "dwarf_macho_loader.h" #include "dwarf_string.h" #ifndef O_BINARY @@ -431,6 +432,39 @@ is_pe_object(int fd, return DW_DLV_ERROR; } +static int +is_mach_o_universal(struct elf_header *h, + unsigned *endian, + unsigned *offsetsize) +{ + unsigned long magicval = 0; + unsigned locendian = 0; + unsigned locoffsetsize = 0; + + /* No swapping here. Need to match size of + the universal-object magic field. */ + magicval = magic_copy(h->e_ident,4); + if (magicval == FAT_MAGIC) { + locendian = DW_END_big; + locoffsetsize = 32; + } else if (magicval == FAT_CIGAM) { + locendian = DW_END_little; + locoffsetsize = 32; + }else if (magicval == FAT_MAGIC_64) { + locendian = DW_END_big; + locoffsetsize = 64; + } else if (magicval == FAT_CIGAM_64) { + locendian = DW_END_little; + locoffsetsize = 64; + } else { + return FALSE; + } + *endian = locendian; + *offsetsize = locoffsetsize; + return TRUE; +} + + static int is_mach_o_magic(struct elf_header *h, unsigned *endian, @@ -470,6 +504,25 @@ dwarf_object_detector_fd(int fd, unsigned *offsetsize, Dwarf_Unsigned *filesize, int *errcode) +{ + Dwarf_Unsigned fileoffsetbase = 0; + int res = 0; + + res = _dwarf_object_detector_fd_a(fd, + ftype,endian,offsetsize, + fileoffsetbase,filesize, + errcode); + return res; +} + +int +_dwarf_object_detector_fd_a(int fd, + unsigned *ftype, + unsigned *endian, + unsigned *offsetsize, + Dwarf_Unsigned fileoffsetbase, + Dwarf_Unsigned *filesize, + int *errcode) { struct elf_header h; size_t readlen = sizeof(h); @@ -477,6 +530,7 @@ dwarf_object_detector_fd(int fd, off_t fsize = 0; off_t lsval = 0; ssize_t readval = 0; + Dwarf_Unsigned remaininglen = 0; fsize = lseek(fd,0L,SEEK_END); if (fsize < 0) { @@ -488,7 +542,19 @@ dwarf_object_detector_fd(int fd, *errcode = DW_DLE_FILE_TOO_SMALL; return DW_DLV_ERROR; } - lsval = lseek(fd,0L,SEEK_SET); + remaininglen = fsize - fileoffsetbase; + if ((Dwarf_Unsigned)fsize <= fileoffsetbase) { + printf("FAIL: fsize <= offsetbase impossible\n"); + *errcode = DW_DLE_SEEK_ERROR; + return DW_DLV_ERROR; + } + if (remaininglen <= readlen) { + /* Not a real object file */ + *errcode = DW_DLE_FILE_TOO_SMALL; + return DW_DLV_ERROR; + } + + lsval = lseek(fd,fileoffsetbase,SEEK_SET); if (lsval < 0) { *errcode = DW_DLE_SEEK_ERROR; return DW_DLV_ERROR; @@ -509,23 +575,28 @@ dwarf_object_detector_fd(int fd, return res; } *ftype = DW_FTYPE_ELF; - *filesize = (size_t)fsize; + *filesize = (Dwarf_Unsigned)fsize; + return DW_DLV_OK; + } + if (is_mach_o_universal(&h,endian,offsetsize)) { + *ftype = DW_FTYPE_APPLEUNIVERSAL; + *filesize = (Dwarf_Unsigned)fsize; return DW_DLV_OK; } if (is_mach_o_magic(&h,endian,offsetsize)) { *ftype = DW_FTYPE_MACH_O; - *filesize = (size_t)fsize; + *filesize = (Dwarf_Unsigned)fsize; return DW_DLV_OK; } if (is_archive_magic(&h)) { *ftype = DW_FTYPE_ARCHIVE; - *filesize = (size_t)fsize; + *filesize = (Dwarf_Unsigned)fsize; return DW_DLV_OK; } res = is_pe_object(fd,fsize,endian,offsetsize,errcode); if (res == DW_DLV_OK ) { *ftype = DW_FTYPE_PE; - *filesize = (size_t)fsize; + *filesize = (Dwarf_Unsigned)fsize; return DW_DLV_OK; } /* Unknown object format. */ diff --git a/bundled/libdwarf/dwarf_object_detector.h b/bundled/libdwarf/dwarf_object_detector.h index 85dfa47..6f513e6 100644 --- a/bundled/libdwarf/dwarf_object_detector.h +++ b/bundled/libdwarf/dwarf_object_detector.h @@ -76,6 +76,15 @@ extern "C" { *errcode when the function returns DW_DLV_ERROR) will hopefully suffice for most purposes. */ +/* Added September 2023 for Mach-O universal binaries */ +int _dwarf_object_detector_fd_a(int dw_fd, + unsigned int *dw_ftype, + unsigned int *dw_endian, + unsigned int *dw_offsetsize, + Dwarf_Unsigned dw_offset_base, + Dwarf_Unsigned *dw_filesize, + int *dw_errcode); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/bundled/libdwarf/dwarf_opaque.h b/bundled/libdwarf/dwarf_opaque.h index 9e6dc06..9bd8c55 100644 --- a/bundled/libdwarf/dwarf_opaque.h +++ b/bundled/libdwarf/dwarf_opaque.h @@ -594,6 +594,7 @@ struct Dwarf_Debug_s { under de_obj_file. */ int de_fd; char de_owns_fd; + char de_in_tdestroy; /* for de_alloc_tree DW202309-001 */ /* DW_PATHSOURCE_BASIC or MACOS or DEBUGLINK */ unsigned char de_path_source; /* de_path is only set automatically if dwarf_init_path() @@ -753,6 +754,14 @@ struct Dwarf_Debug_s { Dwarf_Unsigned de_frame_same_value_number; Dwarf_Unsigned de_frame_undefined_value_number; + /* If count > 0 means the DW_FTYPE_APPLEUNIVERSAL + we initially read has this number of + binaries in it, and de_universalbinary_index + is the index of the current object inside + the universal binary. */ + unsigned int de_universalbinary_count; + unsigned int de_universalbinary_index; + unsigned char de_big_endian_object; /* Non-zero if object being read is big-endian. */ @@ -1010,10 +1019,11 @@ void _dwarf_destruct_elf_nlaccess( extern int _dwarf_macho_setup(int fd, char *true_path, + unsigned universalnumber, unsigned ftype, unsigned endian, unsigned offsetsize, - size_t filesize, + Dwarf_Unsigned filesize, unsigned groupnumber, Dwarf_Handler errhand, Dwarf_Ptr errarg, diff --git a/bundled/libdwarf/dwarf_query.c b/bundled/libdwarf/dwarf_query.c index 52c6c16..cbb0956 100644 --- a/bundled/libdwarf/dwarf_query.c +++ b/bundled/libdwarf/dwarf_query.c @@ -2106,3 +2106,25 @@ int dwarf_cu_header_basics(Dwarf_Die die, } return DW_DLV_OK; } + +int +dwarf_get_universalbinary_count( + Dwarf_Debug dbg, + Dwarf_Unsigned *current_index, + Dwarf_Unsigned *available_count) +{ + if (!dbg) { + return DW_DLV_NO_ENTRY; + } + if (!dbg->de_universalbinary_count ) { + return DW_DLV_NO_ENTRY; + } + if (current_index) { + *current_index = dbg->de_universalbinary_index; + } + if (available_count) { + *available_count = dbg->de_universalbinary_count; + } + return DW_DLV_OK; +} + diff --git a/bundled/libdwarf/dwarf_rnglists.c b/bundled/libdwarf/dwarf_rnglists.c index c0056a5..07b367e 100644 --- a/bundled/libdwarf/dwarf_rnglists.c +++ b/bundled/libdwarf/dwarf_rnglists.c @@ -1274,6 +1274,9 @@ int dwarf_rnglists_get_rle_head( Dwarf_Attribute attr, Dwarf_Half theform, + /* attr_val is either an offset + (theform == DW_FORM_sec_offset) + or an index DW_FORM_rnglistx. */ Dwarf_Unsigned attr_val, Dwarf_Rnglists_Head *head_out, Dwarf_Unsigned *entries_count_out, diff --git a/bundled/libdwarf/dwarf_universal.h b/bundled/libdwarf/dwarf_universal.h new file mode 100644 index 0000000..9742067 --- /dev/null +++ b/bundled/libdwarf/dwarf_universal.h @@ -0,0 +1,63 @@ +/* Copyright (c) 2023, David Anderson +All rights reserved. + +Redistribution and use in source and binary forms, with +or without modification, are permitted provided that the +following conditions are met: + + Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +#ifndef DWARF_UNIVERSAL_H +#define DWARF_UNIVERSAL_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +struct Dwarf_Universal_Head_s; +typedef struct Dwarf_Universal_Head_s * Dwarf_Universal_Head; + +int _dwarf_object_detector_universal_head( + char *dw_path, + Dwarf_Unsigned dw_filesize, + unsigned int *dw_contentcount, + Dwarf_Universal_Head * dw_head, + int *errcode); + +int _dwarf_object_detector_universal_instance( + Dwarf_Universal_Head dw_head, + Dwarf_Unsigned dw_index_of, + Dwarf_Unsigned *dw_cpu_type, + Dwarf_Unsigned *dw_cpu_subtype, + Dwarf_Unsigned *dw_offset, + Dwarf_Unsigned *dw_size, + Dwarf_Unsigned *dw_align, + int *errcode); +void _dwarf_dealloc_universal_head(Dwarf_Universal_Head dw_head); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* DWARF_UNIVERSAL_H */ diff --git a/bundled/libdwarf/libdwarf.h b/bundled/libdwarf/libdwarf.h index 7a85d28..bc0ef7f 100644 --- a/bundled/libdwarf/libdwarf.h +++ b/bundled/libdwarf/libdwarf.h @@ -99,10 +99,10 @@ extern "C" { */ /* Semantic Version identity for this libdwarf.h */ -#define DW_LIBDWARF_VERSION "0.8.0" +#define DW_LIBDWARF_VERSION "0.8.1" #define DW_LIBDWARF_VERSION_MAJOR 0 #define DW_LIBDWARF_VERSION_MINOR 8 -#define DW_LIBDWARF_VERSION_MICRO 0 +#define DW_LIBDWARF_VERSION_MICRO 1 #define DW_PATHSOURCE_unspecified 0 #define DW_PATHSOURCE_basic 1 @@ -115,6 +115,7 @@ extern "C" { #define DW_FTYPE_MACH_O 2 /* MacOS. */ #define DW_FTYPE_PE 3 /* Windows */ #define DW_FTYPE_ARCHIVE 4 /* unix archive */ +#define DW_FTYPE_APPLEUNIVERSAL 5 #endif /* DW_FTYPE_UNKNOWN */ /* standard return values for functions */ #define DW_DLV_NO_ENTRY -1 @@ -1385,9 +1386,10 @@ typedef struct Dwarf_Rnglists_Head_s * Dwarf_Rnglists_Head; #define DW_DLE_LINE_INDEX_WRONG 499 #define DW_DLE_LINE_COUNT_WRONG 500 #define DW_DLE_ARITHMETIC_OVERFLOW 501 +#define DW_DLE_UNIVERSAL_BINARY_ERROR 502 /*! @note DW_DLE_LAST MUST EQUAL LAST ERROR NUMBER */ -#define DW_DLE_LAST 501 +#define DW_DLE_LAST 502 #define DW_DLE_LO_USER 0x10000 /*! @} */ @@ -1403,6 +1405,10 @@ typedef struct Dwarf_Rnglists_Head_s * Dwarf_Rnglists_Head; /*! @brief Initialization based on path, the most common initialization. + On a Mach-O universal binary this function can + only return information about the first (zero index) + object in the universal binary. + @param dw_path Pass in the path to the object file to open. @param dw_true_path_out_buffer @@ -1448,6 +1454,8 @@ typedef struct Dwarf_Rnglists_Head_s * Dwarf_Rnglists_Head; @see dwarf_init_path_dl dwarf_init_b @see exampleinit */ + + DW_API int dwarf_init_path(const char * dw_path, char * dw_true_path_out_buffer, unsigned int dw_true_path_bufferlen, @@ -1457,6 +1465,28 @@ DW_API int dwarf_init_path(const char * dw_path, Dwarf_Debug* dw_dbg, Dwarf_Error* dw_error); +/*! @brief Initialization based on path + + This identical to dwarf_init_path() except that it + adds a new argument, dw_universalnumber, + with which you can specify which object in + a Mach-O universal binary you wish to open. + + It is always safe and appropriate to pass + zero as the dw_universalnumber. + Elf and PE and (non-universal) Mach-O object + files ignore the value of dw_universalnumber. +*/ +DW_API int dwarf_init_path_a(const char * dw_path, + char * dw_true_path_out_buffer, + unsigned int dw_true_path_bufferlen, + unsigned int dw_groupnumber, + unsigned int dw_universalnumber, + Dwarf_Handler dw_errhand, + Dwarf_Ptr dw_errarg, + Dwarf_Debug* dw_dbg, + Dwarf_Error* dw_error); + /*! @brief Initialization following GNU debuglink section data. Sets the true-path with DWARF if there is @@ -1525,6 +1555,35 @@ DW_API int dwarf_init_path_dl(const char * dw_path, unsigned char * dw_dl_path_source, Dwarf_Error* dw_error); +/*! @brief Initialization based on path with debuglink + + This identical to dwarf_init_path_dl() except that it + adds a new argument, dw_universalnumber, + with which you can specify which object in + a Mach-O universal binary you wish to open. + + It is always safe and appropriate to pass + zero as the dw_universalnumber. + Elf and PE and (non-universal) Mach-O object + files ignore the value of dw_universalnumber. + + Mach-O objects do not contain or use debuglink + data. +*/ + +DW_API int dwarf_init_path_dl_a(const char * dw_path, + char * dw_true_path_out_buffer, + unsigned int dw_true_path_bufferlen, + unsigned int dw_groupnumber, + unsigned int dw_universalnumber, + Dwarf_Handler dw_errhand, + Dwarf_Ptr dw_errarg, + Dwarf_Debug* dw_dbg, + char ** dw_dl_path_array, + unsigned int dw_dl_path_array_size, + unsigned char * dw_dl_path_source, + Dwarf_Error* dw_error); + /*! @brief Initialization based on Unix/Linux (etc) path This version allows specifying any number of debuglink global paths to search on for debuglink targets. @@ -3964,7 +4023,8 @@ DW_API void dwarf_dealloc_ranges(Dwarf_Debug dw_dbg, @param dw_attr The attribute referring to .debug_rnglists @param dw_theform - The form number. + The form number, DW_FORM_sec_offset or + DW_FORM_rnglistx. @param dw_index_or_offset_value If the form is an index, pass it here. If the form is an offset, pass that here. @@ -5401,7 +5461,7 @@ DW_API int dwarf_get_fde_info_for_reg3_b(Dwarf_Fde dw_fde, dwarf_get_fde_info_for_reg3_c but it refers to the CFA (which is not part of the register table) so function has no table column argument. - + New in September 2023, release 0.8.0. dwarf_get_fde_info_for_cfa_reg3_c() returns dw_offset as a signed type. @@ -5428,13 +5488,13 @@ DW_API int dwarf_get_fde_info_for_cfa_reg3_c(Dwarf_Fde dw_fde, Dwarf_Bool * dw_has_more_rows, Dwarf_Addr * dw_subsequent_pc, Dwarf_Error * dw_error); -/*! @brief Get the value of the CFA for a particular pc value(obsolete) +/*! @brief Get the value of the CFA for a particular pc value @see dwarf_get_fde_info_for_cfa_reg3_c - This is the earlier version that returns a dw_offset - of Dwarf_Unsigned, requiring you to cast to Dwarf_Signed - to work with the value. + This is the earlier version that returns a dw_offset + of type Dwarf_Unsigned, requiring you to cast to Dwarf_Signed + to work with the value. */ DW_API int dwarf_get_fde_info_for_cfa_reg3_b(Dwarf_Fde dw_fde, @@ -8846,11 +8906,50 @@ DW_API Dwarf_Small dwarf_set_default_address_size( Dwarf_Debug dw_dbg, Dwarf_Small dw_value); +/*! @brief Retrieve universal binary index + + For Mach-O universal binaries this returns + relevant information. + + For non-universal binaries (Mach-O, Elf, + or PE) the values are not meaningful, so + the function returns DW_DLV_NO_ENTRY.. + + @param dw_dbg + The Dwarf_Debug of interest. + @param dw_current_index + If dw_current_index is passed in non-null the function + returns the universal-binary index of the current + object (which came from a universal binary). + @param dw_available_count + If dw_current_index is passed in non-null the function + returns the count of binaries in + the universal binary. + @return + Returns DW_DLV_NO_ENTRY if the object file is + not from a Mach-O universal binary. + Returns DW_DLV_NO_ENTRY if dw_dbg is passed in NULL. + Never returns DW_DLV_ERROR. +*/ +DW_API int dwarf_get_universalbinary_count( + Dwarf_Debug dw_dbg, + Dwarf_Unsigned *dw_current_index, + Dwarf_Unsigned *dw_available_count); + + /*! @} */ /*! @defgroup objectdetector Determine Object Type of a File @{ + + This group of functions are unlikely to be called + by your code unless your code needs to know + the basic data about an object file without + actually opening a Dwarf_Debug. + + These are crucial for libdwarf itself. + */ DW_API int dwarf_object_detector_path_b(const char * dw_path, char *dw_outpath_buffer,