ultimatepp/uppdev/coff/uld/obj.h
cxl 3cd394812c Merge continued
git-svn-id: svn://ultimatepp.org/upp/trunk@10263 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2016-10-04 08:34:39 +00:00

591 lines
18 KiB
C++

#ifndef _console_uld_obj_h_
#define _console_uld_obj_h_
static inline int CoffSectionAlignShift(int flags)
{
int v = (flags >> 20) & 15;
return v ? v - 1 : 2;
}
static inline int CoffGetLengthAlignment(int align, int length)
{
/*
for(int i = 1; i < align; i <<= 1)
if(length & i)
return i;
*/
return align;
}
typedef int atom_t;
class LinkJob;
class ObjSec : Moveable<ObjSec>
{
public:
ObjSec() {}
ObjSec(const Nuller& nuller) : object(-1), section(0) {}
ObjSec(int object, int section) : object(object), section(section) {}
unsigned GetHashValue() const { return CombineHash(::GetHashValue(object), ::GetHashValue(section)); }
bool IsNullInstance() const { return object < 0; }
public:
int object;
int section;
};
inline bool operator == (const ObjSec& a, const ObjSec& b) { return a.object == b.object && a.section == b.section; }
inline bool operator != (const ObjSec& a, const ObjSec& b) { return !(a == b); }
NTL_MOVEABLE(COFF_IMAGE_SYMBOL)
class ObjectFile
{
public:
enum FILETYPE { DIRECT, FULL_PATH, LIB_PATH, DEFAULTLIB, INTERNAL, };
ObjectFile(LinkJob& job, int index, String library_file, String object_file,
FILETYPE filetype, int library_offset, Time file_time, int object_size);
void ReadFile(const byte *mapping);
String ToString() const;
void Dump() const;
public:
enum SEC_TYPE { SEC_ANON_COMDAT, SEC_STD, SEC_STAB, SEC_STABSTR, /*SEC_INULL,*/ SEC_RAW };
enum COM_STATE { COM_UNK, COM_SELECTED, COM_TRASHED };
struct Symbol : Moveable<Symbol>
{
Symbol() {}
Symbol(int section_atom, int value) : section_atom(section_atom), value(value) {}
int section_atom; // section > 0 -> section; 0 = absolute; < 0 -> ~atom
int value;
};
struct Section
{
Section() : name_atom(0), sec_atom(0), size(0), raw_size(0), offset(0), flags(0), type(SEC_STD)
, ref_sec_index(0), ref_ext_index(0), sec_map_index(-1), comdat_forward(-1)
, used(false), autocollect(false), comdat_state(COM_UNK), comdat_packing(0) {}
int name_atom;
int sec_atom;
int size;
int raw_size;
int offset;
int flags;
SEC_TYPE type;
bool autocollect;
bool used;
COM_STATE comdat_state;
char comdat_packing;
int ref_sec_index;
int ref_ext_index;
int sec_map_index;
int comdat_forward;
Vector<byte> section_data;
Vector<COFF_IMAGE_RELOCATION> coff_reloc;
int coff_reloc_offset;
};
struct Import
{
Import() : app_atom(0), imp_atom(0), ordinal_hint(0), ordinal(false) {}
int app_atom;
int imp_atom;
int ordinal_hint;
bool ordinal;
};
public:
LinkJob& linkjob;
int index;
String library_file;
String object_file;
Time file_time;
int object_size;
Vector<byte> object_data;
int library_offset;
int dll_atom;
int stab_index;
int stabstr_index;
FILETYPE filetype;
bool autocollect;
bool used_any;
bool collected;
bool has_ctors_dtors;
bool export_symbols;
// String directives;
Vector<int> ref_sections;
Vector<int> ref_externals;
Array<Section> sections;
Array<Import> imports;
Index<int> used_stubs;
Index<int> used_imports;
enum
{
SEC_COMDAT,
SEC_DLL_STUBS,
SEC_DLL_NAMES,
SEC_DLL_IMPORTS,
SEC_DLL_BOUND,
SEC_DLL_DESCRIPTOR,
// SEC_DLL_NULL_DESC,
DLL_SECTIONS
};
VectorMap<int, int> comdat_assoc;
Vector<Symbol> coff_symbols;
};
class LinkJob
{
public:
enum
{
COFF_IMAGE_SYM_TYPE_SPECIAL = 0xFF00,
COFF_IMAGE_SYM_TYPE_SECTION,
COFF_IMAGE_SYM_TYPE_IMPORT_NAME,
COFF_IMAGE_SYM_TYPE_IMPORT_ORDINAL,
COFF_IMAGE_SYM_TYPE_IMPORT_STUB,
COFF_IMAGE_SYM_TYPE_BASE,
COFF_IMAGE_SYM_TYPE_CTOR_DTOR,
};
enum SPECIAL_OBJECTS
{
OBJ_MARKER,
OBJ_CTOR,
OBJ_EXPORT,
OBJ_RSRC,
OBJ_FIRST, // first user object
};
enum
{
OBJM_COMDAT,
OBJM_DATA_BEGIN,
OBJM_PSEUDO_RELOC_BEGIN,
OBJM_PSEUDO_RELOC_END,
OBJM_BSS_BEGIN,
OBJM_BSS_END,
OBJM_COUNT,
};
enum
{
OBJC_COMDAT,
OBJC_CTOR_BEGIN,
OBJC_CTOR_END,
OBJC_DTOR_BEGIN,
OBJC_DTOR_END,
OBJC_IDATA_HOLE,
OBJC_IDATA_NULL,
OBJC_COUNT
};
enum
{
OBJE_COMDAT,
OBJE_DIRECTORY,
OBJE_ADDRESS_TABLE,
OBJE_NAME_POINTERS,
OBJE_ORDINALS,
OBJE_NAMES,
OBJE_COUNT,
};
enum
{
OBJR_COMDAT,
OBJR_DIRS,
OBJR_STRINGS,
OBJR_ENTRIES,
OBJR_DATA,
OBJR_COUNT
};
struct Symbol
{
Symbol(ObjSec obj_sec = Null, int value = 0, word type = 0, bool external = false)
: obj_sec(obj_sec), value(value), type(type)
, linked(false), used(false), relocated(false), external(external) {}
ObjSec obj_sec;
int value;
word type;
bool linked : 1;
bool used : 1;
bool relocated : 1;
bool external : 1;
String ToString() const;
};
enum
{
GRP_CODE,
GRP_RDATA,
GRP_DATA,
GRP_UDATA,
GRP_EDATA,
GRP_IDATA,
GRP_RSRC,
GRP_DEBUG,
GRP_STAB,
GRP_STABSTR,
GRP_SYMBOLS,
GRP_COUNT,
GRP_NONE = -1,
GRP_TEXT_BEGIN = GRP_CODE,
GRP_DATA_BEGIN = GRP_RDATA,
GRP_BSS_BEGIN = GRP_UDATA,
GRP_BSS_END = GRP_UDATA + 1,
};
static String GetGroupName(int group_id);
struct Group
{
int first_section;
int rva;
int rfa;
int raw_size;
};
struct Section
{
Section() : obj_sec(Null), udata(false), group(0), app_section(0), sec_atom(0), rva(-1), rfa(-1), size(0) {}
ObjSec obj_sec;
byte group;
bool udata;
word app_section;
String name;
int sec_atom;
int rva;
int rfa;
int size;
};
struct Stab
{
Stab() : textoff(0), type(0), other(0), desc(0), value(0), /*fileatom(0),*/ fixup(Null) {}
int textoff;
byte type;
byte other;
word desc;
int value;
// int fileatom;
ObjSec fixup;
// unsigned GetHashValue() const;
// bool Equals(const Stab& b) const;
// friend bool operator == (const Stab& a, const Stab& b) { return a.Equals(b); }
// friend bool operator != (const Stab& a, const Stab& b) { return !a.Equals(b); }
};
struct Export
{
Export(String export_name, int ordinal) : export_name(export_name), ordinal(ordinal) {}
String export_name;
int ordinal;
};
struct Resource
{
Resource() : name_id(Null), type_id(Null), lang_id(Null) {}
static bool Sort(const Resource& r, const Resource& s);
WString name;
WString type;
int name_id;
int type_id;
int lang_id;
String data;
};
struct Cache
{
FileMapping mapping;
int lock;
};
/*
struct Cache
{
String library;
String file;
Time time;
int offset;
int size;
void Serialize(Stream& stream);
};
*/
struct AtomOrder
{
AtomOrder(const LinkJob& linkjob) : linkjob(linkjob), langinfo(GetLanguageInfo()) {}
bool operator () (int a, int b) const { return langinfo(linkjob[a], linkjob[b]); }
const LinkJob& linkjob;
const LanguageInfo& langinfo;
};
struct GlobalAddressOrder
{
GlobalAddressOrder(const LinkJob& linkjob) : linkjob(linkjob), langinfo(GetLanguageInfo()) {}
bool operator () (int a, int b) const;
const LinkJob& linkjob;
const LanguageInfo& langinfo;
};
static bool Less(const Section& a, const Section& b);
public:
LinkJob();
static String Usage();
void ReadCommand(const Vector<String>& cmdline, bool user);
void ReadCommand(const char *cmdline, bool user);
void ReadDefaultLibs();
void Link();
void LoadFile(String file, bool defaultlib);
void LoadObject(String file, const FileMapping& mapping, ObjectFile::FILETYPE filetype);
void LoadDLL(String file, const FileMapping& mapping, ObjectFile::FILETYPE filetype);
void LoadLibrary(String file, const FileMapping& mapping, ObjectFile::FILETYPE filetype);
void LoadResource(String file, const FileMapping& mapping);
void SetEntryPoint();
void SetExportSymbols();
void SetRootSymbols();
void PrepareResourceTree();
void CollectSymbols();
void CollectSectionSymbols(Index<ObjSec>& collect_objsec, int referer_index);
void CollectObject(int index);
void CheckDuplicates();
void CollectImports();
void CollectExports();
void CollectSections();
void PrepareImageHeader();
void RelocateGlobals();
void RelocateExports();
void PrepareImageInfo();
void WriteImageFile();
// void OpenCacheFile();
// void SaveCacheFile();
void WriteImageSections();
void RelocateImport(ObjectFile& of);
void RelocateObject(ObjectFile& of);
void RelocateInternal(ObjectFile& of);
void RelocateStabs(ObjectFile& of, const byte *object_ptr);
void RelocateResource(ObjectFile& of);
void CheckUnresolved();
void PrepareSymbolTable();
void PrepareStabBlocks();
void PrepareFixupBlocks();
void WriteMapFile();
void WriteMapGlobals(String& map, const Vector<int>& used, String name);
atom_t Atomize(String atom) { return atoms.FindAdd(atom); }
String operator [] (atom_t atom) const { return atoms[atom]; }
atom_t NameAtom(const COFF_IMAGE_SYMBOL& isym, const char *strtbl) { return Atomize(COFFSymbolName(isym, strtbl)); }
String DemangleAtom(atom_t atom) const;
FileMapping& GetMapping(String filename);
void LockMapping(String filename);
void UnlockMapping(String filename);
ObjectFile::Section& GetSection(ObjSec os) { return objects[os.object].sections[os.section]; }
const ObjectFile::Section& GetSection(ObjSec os) const { return objects[os.object].sections[os.section]; }
// const ObjectFile::Section& GetSection0(ObjSec os) const { return objects[os.section ? os.object : 0].sections[os.section]; }
String FormatSection(ObjSec os) const;
void AddExternal(atom_t atom, ObjSec obj_sec) { ext_obj_sec.Add(atom, obj_sec); }
void AddWeakExternal(atom_t atom, int refatom);
void AddGlobal(atom_t atom, const Symbol& symbol);
void AddCollect(atom_t atom) { collected_symbols.FindAdd(atom, -1); }
bool AddCOFFSymbol(String name, int object, const COFF_IMAGE_SYMBOL& sym);
void AddAuxCOFFSymbol(const COFF_IMAGE_SYMBOL& sym);
void Dump() const;
public:
enum
{
DUMP_IMPORT_LIBS = 0x00000001,
DUMP_OBJECT_LIBS = 0x00000002,
DUMP_COLLECTOR = 0x00000004,
DUMP_REF_FIXUPS = 0x00000008,
DUMP_SECTIONS = 0x00000010,
DUMP_SECTIONS_ALL = 0x00000020,
DUMP_SEC_DEFINES = 0x00000040,
DUMP_STAT = 0x00000080,
DUMP_IMPORT = 0x00000100,
DUMP_OBJECTS = 0x00000200,
DUMP_TIMING = 0x00000400,
DUMP_MAP_UNUSED = 0x00000800,
DUMP_STABS = 0x00001000,
DUMP_STAB_TYPES = 0x00002000,
DUMP_MAP_ALL = 0x00004000,
DUMP_EXPORTS = 0x00008000,
DUMP_DLL_EXPORTS = 0x00010000,
DUMP_COMMANDLINE = 0x00020000,
DUMP_ENVIRONMENT = 0x00040000,
DUMP_RESOURCES = 0x00080000,
};
int dump_flags;
Vector<String> libpaths;
Index<String> defaultlibs;
Index<String> nodefaultlibs;
String dll_search_prefix;
int subsystem;
int machine;
String outputfile;
String mapfile;
bool write_mapfile;
bool mapfile_stdout;
bool write_xref;
signed char debug_info_raw;
bool debug_info;
bool show_logo;
bool autocollect_crt_only;
bool ignore_code_alignment;
bool merge_gcc_sections;
bool static_libraries;
bool make_dll;
bool auto_dll_base;
// bool cache_objects;
bool cache_object_data;
bool verbose;
word major_version;
word minor_version;
enum MODE { MODE_MSLINK, MODE_GNULD };
MODE linkermode;
int file_align;
int image_align;
int image_base;
bool image_fixed;
bool force_reloc;
int stack_reserve;
int stack_commit;
int heap_reserve;
int heap_commit;
Index<String> atoms;
atom_t text_atom;
atom_t data_atom;
atom_t edata_atom;
atom_t crt_atom;
atom_t ctors_atom;
atom_t dtors_atom;
atom_t gcc_except_atom;
atom_t CTOR_LIST_atom;
atom_t _CTOR_LIST_atom;
atom_t CTOR_LIST_END_atom;
atom_t DTOR_LIST_atom;
atom_t _DTOR_LIST_atom;
atom_t DTOR_LIST_END_atom;
atom_t idata_atom;
atom_t idata_idesc_atom;
atom_t idata_inull_atom;
atom_t idata_iat1_atom;
atom_t idata_iat2_atom;
atom_t idata_names_atom;
atom_t rdata_atom;
atom_t bss_atom;
atom_t debug_atom;
atom_t drectve_atom;
atom_t stab_atom;
atom_t stabstr_atom;
atom_t rsrc_atom;
// int mangling_style;
enum { IMP_STUB_SIZE = 6, IMP_ENTRY_SIZE = 4 };
// Array<Cache> object_cache;
// Index<String> cache_name_index;
// Index<String> cache_library_index;
// FileStream cache_file;
// String cache_file_name;
// bool cache_dirty;
Vector<String> command_args;
Index<String> loaded_files;
Array<ObjectFile> objects;
VectorMap<atom_t, int> dll_objects; // dll name -> index into objects
Vector<atom_t> used_dll_objects;
int stab_section;
int stabstr_section;
int symbol_section;
int reloc_section;
int section_count;
bool has_stabs;
// bool has_symbols;
// bool has_relocs;
String entrypoint;
atom_t entrypoint_atom;
VectorMap<atom_t, int> collected_symbols;
VectorMap<atom_t, Index<atom_t> > collected_referer;
VectorMap<atom_t, atom_t> weak_externals;
VectorMap<atom_t, atom_t> section_merge;
ArrayMap<atom_t, Symbol> globals;
Index<ObjSec> global_obj_sec_index;
VectorMap<Point, int> obj_static_global_index;
VectorMap<atom_t, ObjSec> ext_obj_sec;
ArrayMap<String, Cache> mapping_cache;
int mapping_cache_limit;
Segtor<Section, 256> section_map;
Index<int> section_object_index;
// Index<ObjSec> section_obj_sec_index;
VectorMap<atom_t, int> section_name_map; // atom -> sec_map_index
Group groups[GRP_COUNT + 1];
Index<atom_t> unresolved;
Vector<COFF_IMAGE_SYMBOL> coff_output_symbols;
String coff_output_symbol_strings;
// Vector<int> coff_reloc_offsets;
SegtorMap<atom_t, Export, 256> exports;
Index<atom_t> include_symbols;
Array<Resource> resource_objects;
Vector<byte> output_image_header;
Vector<byte> output_fixups;
int output_fixup_size;
VectorMap<String, int> stab_bincl_map;
Vector<byte> output_stab_info;
Vector<char> output_stab_strings;
VectorMap<unsigned, int> output_stab_string_hash;
Vector<int> highlow_fixup_rva;
time_t timestamp;
int ifhdr_pos;
int iohdr_pos;
int secmap_pos;
int header_size;
int code_rva;
int code_rfa;
int idesc_rva;
int idesc_end_rva;
int rsrc_rva;
int rsrc_end_rva;
int iat2_rva;
int iat2_end_rva;
int idata_last;
bool idata_null_found;
int start_time;
String stub_filename;
};
#endif//_console_uld_obj_h_