/* * Deals with LX and LE images. * We must try grab information from the object table. */ static dip_status FindHLLInLXImage( imp_image_handle *ii, unsigned long nh_off ) { union { os2_flat_header flat; object_record obj; } buf; dip_status rc; /* read the header */ rc = DCReadAt( ii->sym_file, &buf.flat, sizeof( buf.flat ), nh_off ); if( rc & DS_ERR ) { return( rc ); } rc = DS_FAIL; if( buf.flat.debug_off && buf.flat.debug_len ) { ii->is_32bit = 1; rc = FoundHLLSign( ii, buf.flat.debug_off, buf.flat.debug_len ); if( rc == DS_OK ) { unsigned i; /* * Get segment info from the object table. */ if ( DCSeek( ii->sym_file, buf.flat.objtab_off + nh_off, DIG_ORG ) != buf.flat.objtab_off + nh_off ) { return( DS_ERR | DS_FSEEK_FAILED ); } ii->seg_count = buf.flat.num_objects; ii->segments = DCAlloc( sizeof( hllinfo_seg ) * ii->seg_count ); if( ii->segments == NULL ) { return( DS_ERR | DS_NO_MEM ); } for( i = 0; i < ii->seg_count; i++ ) { if( DCRead( ii->sym_file, &buf.obj, sizeof( buf.obj ) ) != sizeof( buf.obj )) { return( DS_ERR | DS_FREAD_FAILED ); } ii->segments[i].is_executable = !!( buf.obj.flags & OBJ_EXECUTABLE ); ii->segments[i].is_16bit = !( buf.obj.flags & OBJ_BIG ); ii->segments[i].ovl = 0; ii->segments[i].map.offset = 0; ii->segments[i].map.segment = i + 1; ii->segments[i].size = buf.obj.size; ii->segments[i].address = buf.obj.addr; } } } return( rc ); }
/* * Checks if there is a tailing HLL signature in the file. * * This may work not work on executable images because of file alignments * imposed by the linker (ilink at least). However, TryFindInImage will * deal with those formats, so it doesn't really matter here. */ static dip_status TryFindTrailer( imp_image_handle *ii ) { hll_trailer sig; unsigned long pos; pos = DCSeek( ii->sym_file, DIG_SEEK_POSBACK( sizeof( sig ) ), DIG_END ); if( pos == DIG_SEEK_ERROR ) { return( DS_ERR | DS_FSEEK_FAILED ); } if( DCRead( ii->sym_file, &sig, sizeof( sig ) ) != sizeof( sig ) ) { return( DS_ERR | DS_FREAD_FAILED ); } if( !IsHllSignature( &sig ) ) { return( DS_FAIL ); } pos -= sig.offset - sizeof( sig ); return( FoundHLLSign( ii, pos, sig.offset - sizeof( sig ) ) ); }
/* * Tries to find the HLL/CV debug info in a image which format we know. * This function knows about LX, LE, PE and watcom symfile images. */ static dip_status TryFindInImage( imp_image_handle *ii ) { union { char sig[HLL_SIG_SIZE]; /* ASSUMES >= 4 */ unsigned_16 sig_16; unsigned_32 sig_32; pe_header pe; pe_object sh; debug_directory dbg_dir; } buf; bool have_mz_header = FALSE; unsigned_32 nh_off; dip_status rc; /* Read the image header. */ rc = DCReadAt( ii->sym_file, &buf.sig, sizeof( buf.sig ), 0 ); if( rc & DS_ERR ) { return( rc ); } nh_off = 0; if( buf.sig_16 == DOS_SIGNATURE ) { have_mz_header = TRUE; /* read the new exe header */ rc = DCReadAt( ii->sym_file, &nh_off, sizeof( nh_off ), NH_OFFSET ); if( rc & DS_ERR ) { return( rc ); } rc = DCReadAt( ii->sym_file, &buf.sig, sizeof( buf.sig ), nh_off ); if( rc & DS_ERR ) { return( rc ); } } /* * LE/LX executable - Use the debug_off/len members of the header. */ if( buf.sig_16 == OSF_FLAT_LX_SIGNATURE || buf.sig_16 == OSF_FLAT_SIGNATURE ) { return( FindHLLInLXImage( ii, nh_off ) ); } /* * PE executable - Use or scan the debug directory. */ if( buf.sig_32 == PE_SIGNATURE ) { return( FindHLLInPEImage( ii, nh_off ) ); } /* * NE and MZ executables do not contain any special information * in the header. TryFindTrailer() will have to pick up the debug data. */ if( (buf.sig_16 == OS2_SIGNATURE_WORD) || have_mz_header ) { ii->is_32bit = 0; } /* * ELF executable - ?????? */ /* * A watcom .sym file. */ if( IsHllSignature( &buf ) ) { return( FoundHLLSign( ii, nh_off, ~0UL ) ); } /* no idea what this is.. */ return( DS_FAIL ); }
/* * Deals with 32-bit PE images. */ static dip_status FindHLLInPEImage( imp_image_handle *ii, unsigned long nh_off ) { dip_status rc; unsigned_32 debug_rva; unsigned_32 debug_len; unsigned_32 image_base; unsigned i; unsigned_32 sh_off; union { char sig[HLL_SIG_SIZE]; /* ASSUMES >= 4 */ unsigned_16 sig_16; unsigned_32 sig_32; pe_header pe; pe_object sh; debug_directory dbg_dir; } buf; /* read the header */ rc = DCReadAt( ii->sym_file, &buf.pe, sizeof( buf.pe ), nh_off ); if( rc & DS_ERR ) { return( rc ); } debug_rva = buf.pe.table[ PE_TBL_DEBUG ].rva; debug_len = buf.pe.table[ PE_TBL_DEBUG ].size; if( !debug_rva || !debug_len ) { return( DS_FAIL ); } ii->is_32bit = 1; image_base = buf.pe.image_base; /* * Translate the rva to a file offset and read necessary * segment information at the same time. */ ii->seg_count = buf.pe.num_objects; ii->segments = DCAlloc( sizeof( hllinfo_seg ) * buf.pe.num_objects ); if( ii->segments == NULL ) { return( DS_ERR | DS_NO_MEM ); } sh_off = nh_off /* vv -- watcom mixes the headers :-( */ + offsetof( pe_header, flags ) + sizeof( buf.pe.flags ) + buf.pe.nt_hdr_size; for ( i = 0; i < ii->seg_count; i++, sh_off += sizeof( buf.sh ) ) { rc = DCReadAt( ii->sym_file, &buf.sh, sizeof( buf.sh ), sh_off ); if ( rc & DS_ERR ) { return( rc ); } /* collect segment info. */ ii->segments[i].is_executable = !!( buf.sh.flags & PE_OBJ_CODE ); ii->segments[i].ovl = 0; ii->segments[i].map.offset = 0; ii->segments[i].map.segment = i + 1; ii->segments[i].size = buf.sh.virtual_size; // FIXME: alignment? ii->segments[i].address = buf.sh.rva + image_base; /* is the debug directory section? */ if( !ii->bias && debug_rva - buf.sh.rva < buf.sh.virtual_size ) { unsigned_32 debug_off; int left; debug_off = buf.sh.physical_offset + debug_rva - buf.sh.rva; /* * The IBM linker screw up here. It will omit the debug * directory and put the debug info there instead. * So, before scanning we'll have to check for any HLL sign. */ rc = DCReadAt( ii->sym_file, &buf.dbg_dir, sizeof( buf.dbg_dir ), debug_off ); if( rc & DS_ERR ) { return( rc ); } if( IsHllSignature( &buf ) ) { rc = FoundHLLSign( ii, debug_off, debug_len ); } else { left = debug_len / sizeof( debug_directory ); if( left < 16 ) left = 16; for ( ;; ) { if( buf.dbg_dir.debug_type == DEBUG_TYPE_CODEVIEW ) { /* found something? */ rc = FoundHLLSign( ii, buf.dbg_dir.data_seek, buf.dbg_dir.data_seek ); if( rc == DS_OK || rc & DS_ERR ) { break; } } /* next */ --left; if( left <= 0) { break; } if ( DCRead( ii->sym_file, &buf.dbg_dir, sizeof( buf.dbg_dir ) ) != sizeof( buf.dbg_dir ) ) { break; } } } if( rc & DS_ERR ) { return( rc ); } } } return( ii->bias ? DS_OK : DS_FAIL ); }