forked from KolibriOS/kolibrios
60a4b1c9ef
git-svn-id: svn://kolibrios.org@9683 a494cfbc-eb01-0410-851d-a64ba20cac60
530 lines
21 KiB
C++
530 lines
21 KiB
C++
/**************************** cof2asm.cpp ********************************
|
|
* Author: Agner Fog
|
|
* Date created: 2007-02-25
|
|
* Last modified: 2009-12-20
|
|
* Project: objconv
|
|
* Module: cof2asm.cpp
|
|
* Description:
|
|
* Module for disassembling PE/COFF file
|
|
*
|
|
* Copyright 2007-2009 GNU General Public License http://www.gnu.org/licenses
|
|
*****************************************************************************/
|
|
#include "stdafx.h"
|
|
|
|
CCOF2ASM::CCOF2ASM () {
|
|
// Constructor
|
|
}
|
|
|
|
void CCOF2ASM::Convert() {
|
|
// Do the conversion
|
|
if (ImageBase) Disasm.Init(2, ImageBase); // Executable file or DLL. Set image base
|
|
MakeSectionList(); // Make Sections list and Relocations list in Disasm
|
|
MakeSymbolList(); // Make Symbols list in Disasm
|
|
if (ImageBase) {
|
|
// Executable file
|
|
MakeDynamicRelocations(); // Make dynamic base relocations for executable files
|
|
MakeImportList(); // Make imported symbols for executable files
|
|
MakeExportList(); // Make exported symbols for executable files
|
|
MakeListLabels(); // Put labels on all image directory tables
|
|
}
|
|
Disasm.Go(); // Disassemble
|
|
*this << Disasm.OutFile; // Take over output file from Disasm
|
|
}
|
|
|
|
void CCOF2ASM::MakeSectionList() {
|
|
// Make Sections list and Relocations list in Disasm
|
|
uint32 isec; // Section index
|
|
uint32 irel; // Relocation index
|
|
|
|
// Loop through sections
|
|
for (isec = 0; isec < (uint32)NSections; isec++) {
|
|
|
|
// Get section header
|
|
SCOFF_SectionHeader * SectionHeader = &SectionHeaders[isec];
|
|
|
|
// Section properties
|
|
const char * Name = GetSectionName(SectionHeader->Name);
|
|
uint8 * Buffer = (uint8*)Buf() + SectionHeader->PRawData;
|
|
uint32 InitSize = SectionHeader->SizeOfRawData;
|
|
uint32 TotalSize = SectionHeader->VirtualSize;
|
|
|
|
uint32 SectionAddress = SectionHeader->VirtualAddress;
|
|
uint32 Type = (SectionHeader->Flags & PE_SCN_CNT_CODE) ? 1 : 2;
|
|
if (SectionHeader->Flags & PE_SCN_CNT_UNINIT_DATA) {
|
|
// BSS segment. No data in file
|
|
Buffer = 0;
|
|
Type = 3;
|
|
}
|
|
else if (!(SectionHeader->Flags & (PE_SCN_MEM_WRITE | PE_SCN_MEM_EXECUTE))) {
|
|
// Constant segment
|
|
Type = 4;
|
|
}
|
|
if (SectionHeader->Flags & PE_SCN_LNK_COMDAT) {
|
|
// Communal section
|
|
Type |= 0x1000;
|
|
}
|
|
if (strnicmp(Name,"debug",5) == 0 || strnicmp(Name+1,"debug",5) == 0) {
|
|
// This is a debug section
|
|
Type = 0x10;
|
|
}
|
|
if (strnicmp(Name,".pdata", 6) == 0) {
|
|
// This section has exception information
|
|
Type = 0x11;
|
|
}
|
|
|
|
uint32 Align = (SectionHeader->Flags & PE_SCN_ALIGN_MASK) / PE_SCN_ALIGN_1;
|
|
if (Align) Align--;
|
|
|
|
// Save section record
|
|
Disasm.AddSection(Buffer, InitSize, TotalSize, SectionAddress, Type, Align, WordSize, Name);
|
|
|
|
// Get relocations
|
|
// Pointer to relocation entry
|
|
union {
|
|
SCOFF_Relocation * p; // pointer to record
|
|
int8 * b; // used for address calculation and incrementing
|
|
} Reloc;
|
|
Reloc.b = Buf() + SectionHeader->PRelocations;
|
|
|
|
for (irel = 0; irel < SectionHeader->NRelocations; irel++, Reloc.b += SIZE_SCOFF_Relocation) {
|
|
|
|
// Relocation properties
|
|
int32 Section = isec + 1;
|
|
uint32 Offset = Reloc.p->VirtualAddress;
|
|
int32 Addend = 0;
|
|
uint32 TargetIndex = Reloc.p->SymbolTableIndex;
|
|
|
|
// Translate relocation type
|
|
uint32 Type = 0, Size = 0;
|
|
if (WordSize == 32) {
|
|
// 32 bit relocation types
|
|
// 0 = unknown, 1 = direct, 2 = self-relative, 3 = image-relative, 4 = segment relative
|
|
switch(Reloc.p->Type) {
|
|
case COFF32_RELOC_ABS: // Ignore
|
|
continue;
|
|
case COFF32_RELOC_DIR32: // Direct, 32 bits
|
|
Type = 1;
|
|
Size = 4;
|
|
break;
|
|
case COFF32_RELOC_REL32: // Self-relative, 32 bits
|
|
Type = 2;
|
|
Size = 4;
|
|
Addend = -4;
|
|
break;
|
|
case COFF32_RELOC_IMGREL: // Image relative, 32 bits
|
|
Type = 4;
|
|
Size = 4;
|
|
break;
|
|
case COFF32_RELOC_SECREL: // Section relative, 32 bits
|
|
Type = 8;
|
|
Size = 4;
|
|
break;
|
|
case COFF32_RELOC_SECTION: // Section index of symbol, 16 bits
|
|
Type = 0x200;
|
|
Size = 2;
|
|
break;
|
|
default: // Other/unknown
|
|
Type = 0;
|
|
Size = 4;
|
|
}
|
|
}
|
|
else { // WordSize = 64
|
|
switch(Reloc.p->Type) {
|
|
case COFF64_RELOC_ABS: // Ignore
|
|
continue;
|
|
case COFF64_RELOC_ABS32: // Absolute 32 bit
|
|
Type = 1;
|
|
Size = 4;
|
|
break;
|
|
case COFF64_RELOC_ABS64: // Absolute 64 bit
|
|
Type = 1;
|
|
Size = 8;
|
|
break;
|
|
case COFF64_RELOC_IMGREL: // Image relative 32 bit
|
|
Type = 4;
|
|
Size = 4;
|
|
break;
|
|
case COFF64_RELOC_REL32: // Self-relative, 32 bits
|
|
case COFF64_RELOC_REL32_1: // Self-relative + 1
|
|
case COFF64_RELOC_REL32_2: // Self-relative + 2
|
|
case COFF64_RELOC_REL32_3: // Self-relative + 3
|
|
case COFF64_RELOC_REL32_4: // Self-relative + 4
|
|
case COFF64_RELOC_REL32_5: // Self-relative + 5
|
|
Type = 2;
|
|
Size = 4;
|
|
Addend = - (Reloc.p->Type + 4 - COFF64_RELOC_REL32);
|
|
break;
|
|
case COFF64_RELOC_SECREL: // Section relative
|
|
Type = 8;
|
|
Size = 4;
|
|
break;
|
|
default: // Other/unknown
|
|
Type = 0;
|
|
Size = 4;
|
|
}
|
|
}
|
|
// Save relocation record
|
|
Disasm.AddRelocation(Section, Offset, Addend, Type, Size, TargetIndex);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CCOF2ASM::MakeSymbolList() {
|
|
// Make Symbols list in Disasm
|
|
uint32 isym; // Symbol index
|
|
uint32 naux = 0; // Number of auxiliary entries in old symbol table
|
|
|
|
union { // Pointer to old symbol table entries
|
|
SCOFF_SymTableEntry * p; // Normal pointer
|
|
int8 * b; // Used for address calculation
|
|
} Sym, SymAux;
|
|
|
|
// Set pointer to old SymbolTable
|
|
Sym.p = SymbolTable;
|
|
|
|
// Loop through old symbol table
|
|
for (isym = 0; isym < (uint32)NumberOfSymbols; isym += 1+naux, Sym.b += (1+naux) * SIZE_SCOFF_SymTableEntry) {
|
|
|
|
// Number of auxiliary entries
|
|
naux = Sym.p->s.NumAuxSymbols;
|
|
|
|
if (Sym.p->s.SectionNumber != COFF_SECTION_ABSOLUTE
|
|
&& (Sym.p->s.SectionNumber < 0
|
|
|| (Sym.p->s.StorageClass != COFF_CLASS_EXTERNAL && Sym.p->s.StorageClass != COFF_CLASS_STATIC && Sym.p->s.StorageClass != COFF_CLASS_LABEL))) {
|
|
// Ignore irrelevant symbol table entries
|
|
continue;
|
|
}
|
|
|
|
// Symbol properties
|
|
uint32 Index = isym;
|
|
int32 Section = Sym.p->s.SectionNumber;
|
|
uint32 Offset = Sym.p->s.Value;
|
|
uint32 Size = 0;
|
|
uint32 Type = (Sym.p->s.Type == COFF_TYPE_FUNCTION) ? 0x83 : 0;
|
|
|
|
// Identify segment entries in symbol table
|
|
if (Sym.p->s.Value == 0 && Sym.p->s.StorageClass == COFF_CLASS_STATIC
|
|
&& naux && Sym.p->s.Type != 0x20) {
|
|
// Note: The official MS specification says that a symbol table entry
|
|
// is a section if the storage class is static and the value is 0,
|
|
// but I have encountered static functions that meet these criteria.
|
|
// Therefore, I am also checking Type and naux.
|
|
Type = 0x80000082;
|
|
}
|
|
|
|
const char * Name = GetSymbolName(Sym.p->s.Name);
|
|
|
|
// Get scope. Note that these values are different from the constants defined in maindef.h
|
|
uint32 Scope = 0;
|
|
if (Sym.p->s.StorageClass == COFF_CLASS_STATIC || Sym.p->s.StorageClass == COFF_CLASS_LABEL) {
|
|
Scope = 2; // Local
|
|
}
|
|
else if (Sym.p->s.SectionNumber > 0 || (Sym.p->s.SectionNumber == -1 && Sym.p->s.StorageClass == COFF_CLASS_EXTERNAL)) {
|
|
Scope = 4; // Public
|
|
}
|
|
else {
|
|
Scope = 0x20; // External
|
|
}
|
|
|
|
// Check auxiliary symbol table entries
|
|
if (naux && Sym.p->s.Type == COFF_TYPE_FUNCTION) {
|
|
// Function symbol has auxiliary entry. Get information about size
|
|
SymAux.b = Sym.b + SIZE_SCOFF_SymTableEntry;
|
|
Size = SymAux.p->func.TotalSize;
|
|
}
|
|
// Check for special section values
|
|
if (Section < 0) {
|
|
if (Section == COFF_SECTION_ABSOLUTE) {
|
|
// Symbol is an absolute constant
|
|
Section = ASM_SEGMENT_ABSOLUTE;
|
|
}
|
|
else {
|
|
// Debug symbols, etc
|
|
Section = ASM_SEGMENT_ERROR;
|
|
}
|
|
}
|
|
|
|
// Store new symbol record
|
|
Disasm.AddSymbol(Section, Offset, Size, Type, Scope, Index, Name);
|
|
}
|
|
}
|
|
|
|
void CCOF2ASM::MakeDynamicRelocations() {
|
|
// Make dynamic base relocations for executable files
|
|
|
|
// Find base relocation table
|
|
SCOFF_ImageDirAddress reldir;
|
|
if (!GetImageDir(5, &reldir)) {
|
|
// No base relocation table found
|
|
return;
|
|
}
|
|
|
|
SCOFF_BaseRelocationBlock * pBaseRelocation; // Start of dynamic base relocation section
|
|
|
|
// Beginning of .reloc section is first base relocation block
|
|
pBaseRelocation = &Get<SCOFF_BaseRelocationBlock>(reldir.FileOffset);
|
|
|
|
uint32 ROffset = 0; // Offset into .reloc section
|
|
uint32 BlockEnd; // Offset of end of current block
|
|
uint32 PageOffset; // Image-relative address of begin of page
|
|
|
|
// Make pointer to header or entry in .reloc section
|
|
union {
|
|
SCOFF_BaseRelocationBlock * header;
|
|
SCOFF_BaseRelocation * entry;
|
|
int8 * b;
|
|
} Pointer;
|
|
|
|
// Loop throung .reloc section
|
|
// while (ROffset < reldir.MaxOffset) {
|
|
while (ROffset < reldir.Size) {
|
|
// Set Pointer to current position
|
|
Pointer.header = pBaseRelocation;
|
|
Pointer.b += ROffset;
|
|
|
|
// Read base relocation block
|
|
PageOffset = Pointer.header->PageRVA;
|
|
BlockEnd = ROffset + Pointer.header->BlockSize;
|
|
|
|
// Read entries in this block
|
|
ROffset += sizeof(SCOFF_BaseRelocationBlock);
|
|
Pointer.b += sizeof(SCOFF_BaseRelocationBlock);
|
|
// Loop through entries
|
|
while (ROffset < BlockEnd) {
|
|
// Set Pointer to current position
|
|
Pointer.header = pBaseRelocation;
|
|
Pointer.b += ROffset;
|
|
|
|
if (Pointer.entry->Type == COFF_REL_BASED_HIGHLOW) {
|
|
// Add relocation record, 32 bit
|
|
// Section = ASM_SEGMENT_IMGREL means offset is image-relative
|
|
// Type = 0x20 means already relocated to image base
|
|
Disasm.AddRelocation(ASM_SEGMENT_IMGREL, Pointer.entry->Offset + PageOffset, 0, 0x21, 4, 0);
|
|
}
|
|
else if (Pointer.entry->Type == COFF_REL_BASED_DIR64) {
|
|
// Add relocation record, 64 bit
|
|
Disasm.AddRelocation(ASM_SEGMENT_IMGREL, Pointer.entry->Offset + PageOffset, 0, 0x21, 8, 0);
|
|
}
|
|
|
|
// Go to next
|
|
ROffset += sizeof(SCOFF_BaseRelocation);
|
|
if (Pointer.entry->Type == COFF_REL_BASED_HIGHADJ) ROffset += sizeof(SCOFF_BaseRelocation);
|
|
}
|
|
// Finished block. Align by 4
|
|
ROffset = (ROffset + 3) & uint32(-4);
|
|
}
|
|
}
|
|
|
|
void CCOF2ASM::MakeImportList() {
|
|
// Make imported symbols for executable files
|
|
|
|
// Find import table
|
|
SCOFF_ImageDirAddress impdir;
|
|
if (!GetImageDir(1, &impdir)) {
|
|
// No import table found
|
|
return;
|
|
}
|
|
|
|
// Beginning of import section is import directory
|
|
SCOFF_ImportDirectory * pImportDirectory = &Get<SCOFF_ImportDirectory>(impdir.FileOffset);
|
|
|
|
// Check if 64 bit
|
|
int Is64bit = OptionalHeader->h64.Magic == COFF_Magic_PE64; // 1 if 64 bit
|
|
uint32 EntrySize = Is64bit ? 8 : 4; // Size of address table entries
|
|
|
|
uint32 NameOffset; // Offset to name
|
|
const char * SymbolName; // Name of symbol
|
|
const char * DLLName; // Name of DLL containing symbol
|
|
char NameBuffer[64]; // Buffer for creating name of ordinal symbols
|
|
uint32 SectionOffset; // Section-relative address of current entry
|
|
uint32 HintNameOffset; // Section-relative address of hint/name table
|
|
uint32 FirstHintNameOffset = 0; // First HintNameOffset = start of hint/name table
|
|
uint32 AddressTableOffset; // Offset of import address table relative to import lookup table
|
|
|
|
// Pointer to current import directory entry
|
|
SCOFF_ImportDirectory * ImportEntry = pImportDirectory;
|
|
// Pointer to current import lookup table entry
|
|
int32 * LookupEntry = 0;
|
|
// Pointer to current hint/name table entry
|
|
SCOFF_ImportHintName * HintNameEntry;
|
|
|
|
// Loop through import directory until null entry
|
|
while (ImportEntry->DLLNameRVA) {
|
|
// Get DLL name
|
|
NameOffset = ImportEntry->DLLNameRVA - impdir.VirtualAddress;
|
|
if (NameOffset < impdir.MaxOffset) {
|
|
DLLName = &Get<char>(impdir.FileOffset + NameOffset);
|
|
}
|
|
else {
|
|
DLLName = "?";
|
|
}
|
|
|
|
// Get lookup table
|
|
SectionOffset = ImportEntry->ImportLookupTableRVA;
|
|
if (SectionOffset == 0) SectionOffset = ImportEntry->ImportAddressTableRVA;
|
|
if (SectionOffset == 0) continue;
|
|
// Get distance from import lookup table to import address table
|
|
AddressTableOffset = ImportEntry->ImportAddressTableRVA - SectionOffset;
|
|
// Section relative address
|
|
SectionOffset -= impdir.VirtualAddress;
|
|
if (SectionOffset >= impdir.MaxOffset) break; // Out of range
|
|
|
|
// Loop through lookup table
|
|
while (1) {
|
|
// Pointer to lookup table entry
|
|
LookupEntry = &Get<int32>(impdir.FileOffset + SectionOffset);
|
|
|
|
// End when entry is empty
|
|
if (!LookupEntry[0]) break;
|
|
|
|
if (LookupEntry[Is64bit] < 0) {
|
|
// Imported by ordinal. Give it a name
|
|
strncpy(NameBuffer, DLLName, 20);
|
|
// Remove dot from name
|
|
char * dot = strchr(NameBuffer,'.');
|
|
if (dot) *dot = 0;
|
|
// Add ordinal number to name
|
|
sprintf(NameBuffer+strlen(NameBuffer), "_Ordinal_%i", uint16(LookupEntry[0]));
|
|
SymbolName = NameBuffer;
|
|
}
|
|
else {
|
|
// Find entry in hint/name table
|
|
HintNameOffset = (LookupEntry[0] & 0x7FFFFFFF) - impdir.VirtualAddress;
|
|
if (HintNameOffset >= impdir.MaxOffset) goto LOOPNEXT; // Out of range
|
|
if (!FirstHintNameOffset) FirstHintNameOffset = HintNameOffset;
|
|
HintNameEntry = &Get<SCOFF_ImportHintName>(impdir.FileOffset + HintNameOffset);
|
|
// Get name
|
|
SymbolName = HintNameEntry->Name;
|
|
}
|
|
// Add symbol
|
|
Disasm.AddSymbol(ASM_SEGMENT_IMGREL, impdir.VirtualAddress + SectionOffset + AddressTableOffset,
|
|
EntrySize, 0xC, 0x20, 0, SymbolName, DLLName);
|
|
|
|
// Loop next
|
|
LOOPNEXT:
|
|
SectionOffset += EntrySize;
|
|
}
|
|
|
|
// Loop next
|
|
ImportEntry++;
|
|
}
|
|
|
|
// Make label for import name table
|
|
if (FirstHintNameOffset) {
|
|
Disasm.AddSymbol(ASM_SEGMENT_IMGREL, impdir.VirtualAddress + FirstHintNameOffset, 1, 1, 1, 0, "Import_name_table");
|
|
}
|
|
}
|
|
|
|
void CCOF2ASM::MakeExportList() {
|
|
// Make exported symbols for executable files
|
|
|
|
// Define entry point
|
|
if (OptionalHeader->h32.AddressOfEntryPoint) {
|
|
Disasm.AddSymbol(ASM_SEGMENT_IMGREL, OptionalHeader->h32.AddressOfEntryPoint, 0, 0x83, 4, 0, "Entry_point");
|
|
}
|
|
|
|
// Get export table directory address
|
|
SCOFF_ImageDirAddress expdir;
|
|
|
|
// Exported names
|
|
if (!GetImageDir(0, &expdir)) {
|
|
// No export directory
|
|
return;
|
|
}
|
|
|
|
// Beginning of export section is export directory
|
|
SCOFF_ExportDirectory * pExportDirectory = &Get<SCOFF_ExportDirectory>(expdir.FileOffset);
|
|
|
|
// Find ExportAddressTable
|
|
uint32 ExportAddressTableOffset = pExportDirectory->ExportAddressTableRVA - expdir.VirtualAddress;
|
|
if (ExportAddressTableOffset == 0 || ExportAddressTableOffset >= expdir.MaxOffset) {
|
|
// Points outside section
|
|
err.submit(2035); return;
|
|
}
|
|
uint32 * pExportAddressTable = &Get<uint32>(expdir.FileOffset + ExportAddressTableOffset);
|
|
|
|
// Find ExportNameTable
|
|
if (pExportDirectory->NamePointerTableRVA == 0) {
|
|
return; // I don't know why this happens
|
|
}
|
|
uint32 ExportNameTableOffset = pExportDirectory->NamePointerTableRVA - expdir.VirtualAddress;
|
|
if (ExportNameTableOffset == 0 || ExportNameTableOffset >= expdir.MaxOffset) {
|
|
// Points outside section
|
|
err.submit(2035); return;
|
|
}
|
|
uint32 * pExportNameTable = &Get<uint32>(expdir.FileOffset + ExportNameTableOffset);
|
|
|
|
// Find ExportOrdinalTable
|
|
uint32 ExportOrdinalTableOffset = pExportDirectory->OrdinalTableRVA - expdir.VirtualAddress;
|
|
if (ExportOrdinalTableOffset == 0 || ExportOrdinalTableOffset >= expdir.MaxOffset) {
|
|
// Points outside section
|
|
err.submit(2035); return;
|
|
}
|
|
uint16 * pExportOrdinalTable = &Get<uint16>(expdir.FileOffset + ExportOrdinalTableOffset);
|
|
|
|
// Get further properties
|
|
uint32 NumExports = pExportDirectory->AddressTableEntries;
|
|
uint32 NumExportNames = pExportDirectory->NamePointerEntries;
|
|
uint32 OrdinalBase = pExportDirectory->OrdinalBase;
|
|
|
|
uint32 i; // Index into pExportOrdinalTable and pExportNameTable
|
|
uint32 Ordinal; // Index into pExportAddressTable
|
|
uint32 Address; // Image-relative address of symbol
|
|
uint32 NameOffset; // Section-relative address of name
|
|
uint32 FirstName = 0; // Image-relative address of first name table entry
|
|
const char * Name = 0; // Name of symbol
|
|
char NameBuffer[64]; // Buffer for making name
|
|
|
|
// Loop through export tables
|
|
for (i = 0; i < NumExports; i++) {
|
|
|
|
Address = 0;
|
|
Name = "?";
|
|
|
|
// Get ordinal from table
|
|
Ordinal = pExportOrdinalTable[i];
|
|
// Address table is indexed by ordinal
|
|
if (Ordinal < NumExports) {
|
|
Address = pExportAddressTable[Ordinal];
|
|
}
|
|
// Find name if there is a name list entry
|
|
if (i < NumExportNames) {
|
|
NameOffset = pExportNameTable[i] - expdir.VirtualAddress;
|
|
if (NameOffset && NameOffset < expdir.MaxOffset) {
|
|
Name = &Get<char>(expdir.FileOffset + NameOffset);
|
|
if (FirstName == 0) FirstName = pExportNameTable[i];
|
|
}
|
|
}
|
|
else {
|
|
// No name. Make name from ordinal number
|
|
sprintf(NameBuffer, "Ordinal_%i", Ordinal + OrdinalBase);
|
|
Name = NameBuffer;
|
|
}
|
|
|
|
// Define symbol
|
|
Disasm.AddSymbol(ASM_SEGMENT_IMGREL, Address, 0, 0x83, 4, 0, Name);
|
|
}
|
|
|
|
// Make label for export section
|
|
Disasm.AddSymbol(ASM_SEGMENT_IMGREL, expdir.VirtualAddress, 4, 3, 2, 0, "Export_tables");
|
|
|
|
// Make labels for export tables
|
|
Disasm.AddSymbol(ASM_SEGMENT_IMGREL, ExportAddressTableOffset - expdir.FileOffset + expdir.VirtualAddress, 4, 3, 2, 0, "Export_address_table");
|
|
Disasm.AddSymbol(ASM_SEGMENT_IMGREL, ExportOrdinalTableOffset - expdir.FileOffset + expdir.VirtualAddress, 4, 3, 2, 0, "Export_ordinal_table");
|
|
Disasm.AddSymbol(ASM_SEGMENT_IMGREL, ExportNameTableOffset - expdir.FileOffset + expdir.VirtualAddress, 4, 3, 2, 0, "Export_name_pointer_table");
|
|
Disasm.AddSymbol(ASM_SEGMENT_IMGREL, FirstName, 1, 1, 2, 0, "Export_name_table");
|
|
}
|
|
|
|
void CCOF2ASM::MakeListLabels() {
|
|
// Attach names to all image directories
|
|
SCOFF_ImageDirAddress dir;
|
|
uint32 i;
|
|
|
|
for (i = 0; i < NumImageDirs; i++) {
|
|
if (GetImageDir(i, &dir)) {
|
|
// Found a directory. Make label for it
|
|
Disasm.AddSymbol(ASM_SEGMENT_IMGREL, dir.VirtualAddress, 4, 0, 1, 0, dir.Name);
|
|
}
|
|
}
|
|
}
|