1 |
36 |
Agner |
/**************************** linker.h ************************************
|
2 |
|
|
* Author: Agner Fog
|
3 |
|
|
* date created: 2017-11-14
|
4 |
|
|
* Last modified: 2020-05-19
|
5 |
|
|
* Version: 1.10
|
6 |
|
|
* Project: Binary tools for ForwardCom instruction set
|
7 |
|
|
* Module: linker.h
|
8 |
|
|
* Description:
|
9 |
|
|
* header file for linker
|
10 |
|
|
*
|
11 |
|
|
* Copyright 2017-2020 GNU General Public License http://www.gnu.org/licenses
|
12 |
|
|
*****************************************************************************/
|
13 |
|
|
|
14 |
|
|
// Structure for list of imported library modules
|
15 |
|
|
struct SLibraryModule {
|
16 |
|
|
uint32_t library; // library number. msb set if symbols have been registered
|
17 |
|
|
uint32_t offset; // offset in executable file or library
|
18 |
|
|
uint32_t modul; // index into modules2 buffer
|
19 |
|
|
};
|
20 |
|
|
|
21 |
|
|
// operator < for sorting library modules
|
22 |
|
|
static inline bool operator < (SLibraryModule const & a, SLibraryModule const & b) {
|
23 |
|
|
if ((a.library << 1) != (b.library << 1)) return (a.library << 1) < (b.library << 1);
|
24 |
|
|
return a.offset < b.offset;
|
25 |
|
|
}
|
26 |
|
|
|
27 |
|
|
// Structure for storing name of relinkable module from input file
|
28 |
|
|
struct SRelinkModule {
|
29 |
|
|
uint32_t libraryName; // name of library that the module comes from (as index into cmd.fileNameBuffer)
|
30 |
|
|
uint32_t moduleName; // name of module (as index into cmd.fileNameBuffer)
|
31 |
|
|
};
|
32 |
|
|
|
33 |
|
|
// operator < for sorting relink module list
|
34 |
|
|
static inline bool operator < (SRelinkModule const & a, SRelinkModule const & b) {
|
35 |
|
|
// compare library names. (libraryName = 0 will give "")
|
36 |
|
|
int j = strcmp(cmd.getFilename(a.libraryName), cmd.getFilename(b.libraryName));
|
37 |
|
|
if (j) return j < 0;
|
38 |
|
|
// compare module names
|
39 |
|
|
j = strcmp(cmd.getFilename(a.moduleName), cmd.getFilename(b.moduleName));
|
40 |
|
|
return j < 0;
|
41 |
|
|
}
|
42 |
|
|
|
43 |
|
|
// operator < for sorting event list
|
44 |
|
|
static inline bool operator < (ElfFwcEvent const & a, ElfFwcEvent const & b) {
|
45 |
|
|
if (a.event != b.event) return a.event < b.event;
|
46 |
|
|
if (a.key != b.key) return a.key < b.key;
|
47 |
|
|
return a.priority > b.priority;
|
48 |
|
|
}
|
49 |
|
|
|
50 |
|
|
|
51 |
|
|
// Structure for list of sections. Sorted by the order in which they should be placed in the executable
|
52 |
|
|
struct SLinkSection {
|
53 |
|
|
uint64_t sh_size; // Section size in bytes
|
54 |
|
|
uint64_t sh_addr; // address in executable
|
55 |
|
|
uint32_t sh_flags; // Section flags
|
56 |
|
|
uint32_t sh_type; // Section type
|
57 |
|
|
uint32_t name; // section name as index into cmd.fileNameBuffer
|
58 |
|
|
uint32_t sh_module; // module containing section (index into modules2)
|
59 |
|
|
uint32_t sectioni; // section index within module
|
60 |
|
|
uint32_t sectionx; // section index in final executable
|
61 |
|
|
uint32_t order; // section must occur in this order in executable file
|
62 |
|
|
uint8_t sh_align; // alignment = 1 << sh_align
|
63 |
|
|
};
|
64 |
|
|
|
65 |
|
|
// Same structure, sorted by sh_module and sectioni
|
66 |
|
|
struct SLinkSection2 : public SLinkSection {
|
67 |
|
|
};
|
68 |
|
|
|
69 |
|
|
// operator < for sorting section list by the order in which they should be placed in the executable
|
70 |
|
|
static inline bool operator < (SLinkSection const & a, SLinkSection const & b) {
|
71 |
|
|
if (a.order != b.order) return a.order < b.order;
|
72 |
|
|
// same type and flags. sort by name
|
73 |
|
|
int j = strcmp(cmd.getFilename(a.name), cmd.getFilename(b.name));
|
74 |
|
|
if (j != 0) return j < 0;
|
75 |
|
|
// same name. sort by module
|
76 |
|
|
return a.sh_module < b.sh_module;
|
77 |
|
|
}
|
78 |
|
|
|
79 |
|
|
// operator < for sorting section list by sh_module and sectioni
|
80 |
|
|
static inline bool operator < (SLinkSection2 const & a, SLinkSection2 const & b) {
|
81 |
|
|
if (a.sh_module != b.sh_module) return a.sh_module < b.sh_module;
|
82 |
|
|
return a.sectioni < b.sectioni;
|
83 |
|
|
}
|
84 |
|
|
|
85 |
|
|
// extended relocation record used temporarily during linking
|
86 |
|
|
struct SReloc2 : public ElfFwcReloc {
|
87 |
|
|
uint32_t modul; // module containing specified r_section
|
88 |
|
|
bool symLocal; // r_sym is in same module. reference by number rather than by name
|
89 |
|
|
bool refSymLocal; // r_refsym is in same module. reference by number rather than by name
|
90 |
|
|
};
|
91 |
|
|
|
92 |
|
|
// symbol cross reference record for connecting symbol records in local modules to records in executable file
|
93 |
|
|
struct SSymbolXref {
|
94 |
|
|
uint32_t name; // symbol name as index into global symbolNameBuffer
|
95 |
|
|
uint32_t modul; // module containing symbol
|
96 |
|
|
uint32_t symi; // index into symbols buffer within module
|
97 |
|
|
uint32_t symx; // index into symbols buffer in outFile
|
98 |
|
|
bool isPublic; // symbol is public or exported
|
99 |
|
|
bool isWeak; // symbol is weak
|
100 |
|
|
};
|
101 |
|
|
|
102 |
|
|
struct SSymbolXref2 : public SSymbolXref {
|
103 |
|
|
};
|
104 |
|
|
|
105 |
|
|
// operator < for sorting symbol cross reference records by modul and symi
|
106 |
|
|
static inline bool operator < (SSymbolXref const & a, SSymbolXref const & b) {
|
107 |
|
|
if (a.modul != b.modul) return a.modul < b.modul;
|
108 |
|
|
return a.symi < b.symi;
|
109 |
|
|
}
|
110 |
|
|
|
111 |
|
|
// operator < for sorting symbol cross reference records by name
|
112 |
|
|
static inline bool operator < (SSymbolXref2 const & a, SSymbolXref2 const & b) {
|
113 |
|
|
return strcmp(symbolNameBuffer.getString(a.name), symbolNameBuffer.getString(b.name)) < 0;
|
114 |
|
|
}
|
115 |
|
|
|
116 |
|
|
// symbol record, sorted by name
|
117 |
|
|
struct SSymbol2 : public ElfFwcSym {
|
118 |
|
|
SSymbol2() {} // default constructor
|
119 |
|
|
SSymbol2(ElfFwcSym const & s) { // constructor to convert from normal symbol record
|
120 |
|
|
*static_cast<ElfFwcSym*>(this) = s;
|
121 |
|
|
}
|
122 |
|
|
};
|
123 |
|
|
|
124 |
|
|
// operator < for sorting symbol recordsby name
|
125 |
|
|
static inline bool operator < (SSymbol2 const & a, SSymbol2 const & b) {
|
126 |
|
|
return strcmp(symbolNameBuffer.getString(a.st_name), symbolNameBuffer.getString(b.st_name)) < 0;
|
127 |
|
|
}
|
128 |
|
|
|
129 |
|
|
|
130 |
|
|
// Class for linking or re-linking executable file
|
131 |
|
|
class CLinker {
|
132 |
|
|
public:
|
133 |
|
|
CLinker(); // Constructor
|
134 |
|
|
void go(); // Do whatever the command line says
|
135 |
|
|
protected:
|
136 |
|
|
void feedBackText1(); // write feedback text on stdout
|
137 |
|
|
void loadExeFile(); // load executable file to be relinked
|
138 |
|
|
void getReplaceNames(); // get names of modules and libraries to remove or replace
|
139 |
|
|
void markSectionsInInputFile(); // check which sections to keep or remove in executable input file
|
140 |
|
|
void extractModule(CELF & modul, uint32_t libname, uint32_t name); // extract a module from executable input file
|
141 |
|
|
void countReusedModules(); // count number of modules and libraries to reuse when relinking
|
142 |
|
|
void getRelinkObjects(); // get all reused objects into modules1 metabuffer
|
143 |
|
|
void extractModuleToFile(CELF & modu); // extract a module from relinkable file if requested
|
144 |
|
|
void getRelinkLibraries(); // recover relinkable library modules
|
145 |
|
|
void feedBackText2(); // write feedback to console
|
146 |
|
|
uint64_t ip_base; // pointer to end of const, begin of code
|
147 |
|
|
uint64_t datap_base; // pointer to end of data, begin of bss
|
148 |
|
|
uint64_t threadp_base; // pointer to begin of thread local memory
|
149 |
|
|
uint64_t entry_point; // entry point for executable startup code
|
150 |
|
|
uint32_t event_table; // address of event table
|
151 |
|
|
uint32_t event_table_num; // number of entries in event table
|
152 |
|
|
uint32_t unresolvedWeak; // there are unresolved weak imports
|
153 |
|
|
uint32_t unresolvedWeakNum; // number of unresolved weak imports for writeable data
|
154 |
|
|
uint32_t dummyConst; // address of dummy constant symbol for unresolved weak imports
|
155 |
|
|
uint32_t dummyData; // address of dummy data symbol for unresolved weak imports
|
156 |
|
|
uint32_t dummyThreadData; // address of dummy thread data symbol for unresolved weak imports
|
157 |
|
|
uint32_t dummyFunc; // address of dummy function for unresolved weak imports
|
158 |
|
|
uint32_t eventDataSize; // total size of all event data sections
|
159 |
|
|
uint32_t numObjects; // number of object files to add
|
160 |
|
|
uint32_t numLibraries; // number of library files to add
|
161 |
|
|
uint32_t numRelinkObjects; // number of relinkable object modules to reuse
|
162 |
|
|
uint32_t numRelinkLibraries; // number of relinkable library files to reuse
|
163 |
|
|
void fillBuffers(); // load specified object files and library files into buffers
|
164 |
|
|
void countModules(); // count number of modules and libraries to add
|
165 |
|
|
void makeSymbolList(); // make list of imported and exported symbols
|
166 |
|
|
void matchSymbols(); // match lists of imported and exported symbols
|
167 |
|
|
void librarySearch(); // search libraries for imported symbols
|
168 |
|
|
void checkDuplicateSymbols(); // check for duplicate symbols
|
169 |
|
|
void readLibraryModules(); // get imported library modules into modules2 buffer
|
170 |
|
|
void makeSectionList(); // make list of all sections
|
171 |
|
|
void sortSections(); // sort sections in the order in which they should occur in the executable file
|
172 |
|
|
void joinCommunalSections(); // join communal sections with same name
|
173 |
|
|
void makeDummySections(); // make dummy segments for unresolved weak externals
|
174 |
|
|
void makeEventList(); // make sorted list of events
|
175 |
|
|
void makeProgramHeaders(); // make program headers and assign addresses to sections
|
176 |
|
|
void specialSymbolsOverride(); // check if automatic symbols have been overridden
|
177 |
|
|
int32_t findModule(uint32_t library, uint32_t memberos);// find a module from a record in symbolExports
|
178 |
|
|
void relocate(); // put values into all cross references
|
179 |
|
|
void checkRegisterUse(ElfFwcSym * sym1, ElfFwcSym * sym2, uint32_t modul);// Check if external function call has compatible register use
|
180 |
|
|
ElfFwcSym * findSymbolAddress(uint64_t * a, uint32_t * targetModule, ElfFwcSym * sym, uint32_t modul); // find a symbol and its address
|
181 |
|
|
uint64_t findSymbolAddress(const char * name); // find the address of a symbol from its name
|
182 |
|
|
void copySections(); // copy sections to output file
|
183 |
|
|
void copySymbols(); // copy symbols to output file
|
184 |
|
|
void copyRelocations(); // copy relocation records to output file if needed
|
185 |
|
|
uint32_t resolveRelocationTarget(uint32_t modul, uint32_t symi);// resolve relocation target for executable file record
|
186 |
|
|
void makeFileHeader(); // make file header
|
187 |
|
|
CELF inputFile; // input file if relinking
|
188 |
|
|
CELF outFile; // output file
|
189 |
|
|
CMetaBuffer<CELF> modules1; // object files and modules from input exe file
|
190 |
|
|
CMetaBuffer<CELF> modules2; // same + object files from libraries
|
191 |
|
|
CMetaBuffer<CLibrary> libraries; // library files
|
192 |
|
|
CDynamicArray<SSymbolEntry> symbolExports; // list of exported symbols
|
193 |
|
|
CDynamicArray<SSymbolEntry> symbolImports; // list of imported symbols
|
194 |
|
|
CDynamicArray<SLinkSection> sections; // list of sections, sorted in memory order
|
195 |
|
|
CDynamicArray<SLinkSection> communalSections;// list of communal sections
|
196 |
|
|
CDynamicArray<SLinkSection2> sections2; // list of sections, sorted by module and section index
|
197 |
|
|
CDynamicArray<SLibraryModule> libmodules; // list of imported library modules
|
198 |
|
|
CDynamicArray<SReloc2> relocations2; // extended relocation records to be copied to executable file
|
199 |
|
|
CDynamicArray<SSymbolXref> symbolXref; // symbol index cross reference
|
200 |
|
|
CDynamicArray<SSymbolXref2> unresWeakSym; // list of unresolved weak symbols
|
201 |
|
|
CDynamicArray<SRelinkModule> relinkModules; // list of modules and libraries in input file to relink
|
202 |
|
|
CDynamicArray<SLCommand> rnames; // List of modules and libraries to delete or replace
|
203 |
|
|
CDynamicArray<ElfFwcEvent> eventData; // container for all event records
|
204 |
|
|
CELF memberBuffer; // buffer containing temporary copy of single library member
|
205 |
|
|
ElfFwcEhdr fileHeader; // file header for executable file
|
206 |
|
|
bool relinkable; // output file is relinkable
|
207 |
|
|
bool relinking; // relinking existing file
|
208 |
|
|
};
|
209 |
|
|
|
210 |
|
|
const uint32_t fillerInstruction = 0x7FFFFFFF; // binary representation of filler instruction
|