void serialize(std::ofstream &file, char ei_class, char ei_data) { // Readjust code offsets for (std::vector<ElfSection *>::iterator c = code.begin(); c != code.end(); c++) (*c)->getShdr().sh_addr += getAddr(); // Apply relocations for (ElfSection *rel = elf->getSection(1); rel != NULL; rel = rel->getNext()) if ((rel->getType() == SHT_REL) || (rel->getType() == SHT_RELA)) { ElfSection *section = rel->getInfo().section; if ((section->getType() == SHT_PROGBITS) && (section->getFlags() & SHF_EXECINSTR)) { if (rel->getType() == SHT_REL) apply_relocations((ElfRel_Section<Elf_Rel> *)rel, section); else apply_relocations((ElfRel_Section<Elf_Rela> *)rel, section); } } ElfSection::serialize(file, ei_class, ei_data); }
int main(int argc, char **argv) { fprintf( stdout, header ); DEBUG(( stderr, "main: parsing command line\n" )); if( parse_cmdline( argc, argv, options, countof(options) ) ) goto bail_out; if( warnings && (linker_options & OPT_ABORT_ON_WARN) ) goto bail_out; if( linker_options & OPT_SHOW_HELP ) { help_msg( help_head, help_tail, options, countof(options) ); goto bail_out; } if( !root_obj ) { error( "no input files" ); goto bail_out; } if( arrange_sections() ) goto bail_out; if( warnings && (linker_options & OPT_ABORT_ON_WARN) ) goto bail_out; adjust_symbols_values(); register_symbols(); resolve_references(); if( warnings && (linker_options & OPT_ABORT_ON_WARN) ) goto bail_out; apply_relocations(); if( warnings && (linker_options & OPT_ABORT_ON_WARN) ) goto bail_out; if( !(linker_options & OPT_MAKE_ORB) ) generate_mt(); if( errors || warnings && (linker_options & OPT_ABORT_ON_WARN) ) goto bail_out; output_sections( output_filename ); if( !(linker_options & OPT_MAKE_ORB) ) output_metadata( output_filename ); if( warnings && (linker_options & OPT_ABORT_ON_WARN) ) goto bail_out; if( linker_options & OPT_XREF ) produce_xrefs( output_filename ); if( errors || (warnings && (linker_options & OPT_ABORT_ON_WARN))) remove(output_filename); else if( linker_options & OPT_VERBOSE ) { fprintf(stdout, "\n" "******************************************************\n" "** %s\n" "**\n", output_filename ); if( linker_options & OPT_MAKE_ORB ) fprintf( stdout, "** ORB generated as:\n" ); else fprintf( stdout, "** Component generated as:\n" ); fprintf(stdout, "** Text at 0x%08x, size 0x%08x\n" "** Data at 0x%08x, size 0x%08x\n" "** BSS at 0x%08x, size 0x%08x\n", comp.text.start, comp.text.size, comp.data.start, comp.data.size, comp.bss.start, comp.bss.size ); if( !(linker_options & OPT_MAKE_ORB) ) fprintf( stdout, "** MTbl at 0x%08x, size 0x%08x\n", comp.mt.start, comp.mt.size ); fprintf(stdout, "******************************************************\n" "\n" ); } bail_out: //global_destruction(); // who cares? we exit anyway... if( errors || warnings ) fprintf( stderr, "exiting with %d error(s), %d warning(s)\n", errors, warnings ); if( warnings && (linker_options & OPT_ABORT_ON_WARN) ) return errors + warnings; return errors; }
/*********************************************************************** * NE_LoadSegment */ BOOL NE_LoadSegment( NE_MODULE *pModule, WORD segnum ) { WORD count; DWORD pos; const struct relocation_entry_s *rep; int size; SEGTABLEENTRY *pSegTable = NE_SEG_TABLE( pModule ); SEGTABLEENTRY *pSeg = pSegTable + segnum - 1; if (pSeg->flags & NE_SEGFLAGS_LOADED) { /* self-loader ? -> already loaded it */ if (pModule->ne_flags & NE_FFLAGS_SELFLOAD) return TRUE; /* leave, except for DGROUP, as this may be the second instance */ if (segnum != pModule->ne_autodata) return TRUE; } if (!pSeg->filepos) return TRUE; /* No file image, just return */ TRACE_(module)("Loading segment %d, hSeg=%04x, flags=%04x\n", segnum, pSeg->hSeg, pSeg->flags ); pos = pSeg->filepos << pModule->ne_align; if (pSeg->size) size = pSeg->size; else size = pSeg->minsize ? pSeg->minsize : 0x10000; if (pModule->ne_flags & NE_FFLAGS_SELFLOAD && segnum > 1) { /* Implement self-loading segments */ SELFLOADHEADER *selfloadheader; void *oldstack; HFILE16 hFile16; WORD args[3]; DWORD ret; selfloadheader = MapSL( MAKESEGPTR(SEL(pSegTable->hSeg),0) ); oldstack = getWOW32Reserved(); setWOW32Reserved((void *)MAKESEGPTR(pModule->self_loading_sel, 0xff00 - sizeof(STACK16FRAME))); hFile16 = NE_OpenFile( pModule ); TRACE_(dll)("Call LoadAppSegProc(hmodule=0x%04x,hf=%x,segnum=%d)\n", pModule->self,hFile16,segnum ); args[2] = pModule->self; args[1] = hFile16; args[0] = segnum; WOWCallback16Ex( (DWORD)selfloadheader->LoadAppSeg, WCB16_PASCAL, sizeof(args), args, &ret ); pSeg->hSeg = LOWORD(ret); TRACE_(dll)("Ret LoadAppSegProc: hSeg=0x%04x\n", pSeg->hSeg); _lclose16( hFile16 ); setWOW32Reserved(oldstack); pSeg->flags |= NE_SEGFLAGS_LOADED; return TRUE; } else if (!(pSeg->flags & NE_SEGFLAGS_ITERATED)) { void *mem = GlobalLock16(pSeg->hSeg); if (!NE_READ_DATA( pModule, mem, pos, size )) return FALSE; pos += size; } else { /* The following bit of code for "iterated segments" was written without any documentation on the format of these segments. It seems to work, but may be missing something. */ const char *buff = NE_GET_DATA( pModule, pos, size ); const char* curr = buff; char *mem = GlobalLock16(pSeg->hSeg); pos += size; if (buff == NULL) return FALSE; while(curr < buff + size) { unsigned int rept = ((const short *)curr)[0]; unsigned int len = ((const short *)curr)[1]; curr += 2*sizeof(short); while (rept--) { memcpy( mem, curr, len ); mem += len; } curr += len; } } pSeg->flags |= NE_SEGFLAGS_LOADED; /* Perform exported function prolog fixups */ NE_FixupSegmentPrologs( pModule, segnum ); if (!(pSeg->flags & NE_SEGFLAGS_RELOC_DATA)) return TRUE; /* No relocation data, we are done */ if (!NE_READ_DATA( pModule, &count, pos, sizeof(count) ) || !count) return TRUE; pos += sizeof(count); TRACE("Fixups for %.*s, segment %d, hSeg %04x\n", *((BYTE *)pModule + pModule->ne_restab), (char *)pModule + pModule->ne_restab + 1, segnum, pSeg->hSeg ); if (!(rep = NE_GET_DATA( pModule, pos, count * sizeof(struct relocation_entry_s) ))) return FALSE; return apply_relocations( pModule, rep, count, segnum ); }