#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 { 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(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 section_data; Vector 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 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 ref_sections; Vector ref_externals; Array
sections; Array imports; Index used_stubs; Index 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 comdat_assoc; Vector 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& 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& 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& 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 libpaths; Index defaultlibs; Index 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 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 object_cache; // Index cache_name_index; // Index cache_library_index; // FileStream cache_file; // String cache_file_name; // bool cache_dirty; Vector command_args; Index loaded_files; Array objects; VectorMap dll_objects; // dll name -> index into objects Vector 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 collected_symbols; VectorMap > collected_referer; VectorMap weak_externals; VectorMap section_merge; ArrayMap globals; Index global_obj_sec_index; VectorMap obj_static_global_index; VectorMap ext_obj_sec; ArrayMap mapping_cache; int mapping_cache_limit; Segtor section_map; Index section_object_index; // Index section_obj_sec_index; VectorMap section_name_map; // atom -> sec_map_index Group groups[GRP_COUNT + 1]; Index unresolved; Vector coff_output_symbols; String coff_output_symbol_strings; // Vector coff_reloc_offsets; SegtorMap exports; Index include_symbols; Array resource_objects; Vector output_image_header; Vector output_fixups; int output_fixup_size; VectorMap stab_bincl_map; Vector output_stab_info; Vector output_stab_strings; VectorMap output_stab_string_hash; Vector 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_