1 | /*****************************************************************************/ |
2 | /* */ |
3 | /* objdata.c */ |
4 | /* */ |
5 | /* Handling object file data for the ld65 linker */ |
6 | /* */ |
7 | /* */ |
8 | /* */ |
9 | /* (C) 1998-2011, Ullrich von Bassewitz */ |
10 | /* Roemerstrasse 52 */ |
11 | /* D-70794 Filderstadt */ |
12 | /* EMail: uz@cc65.org */ |
13 | /* */ |
14 | /* */ |
15 | /* This software is provided 'as-is', without any expressed or implied */ |
16 | /* warranty. In no event will the authors be held liable for any damages */ |
17 | /* arising from the use of this software. */ |
18 | /* */ |
19 | /* Permission is granted to anyone to use this software for any purpose, */ |
20 | /* including commercial applications, and to alter it and redistribute it */ |
21 | /* freely, subject to the following restrictions: */ |
22 | /* */ |
23 | /* 1. The origin of this software must not be misrepresented; you must not */ |
24 | /* claim that you wrote the original software. If you use this software */ |
25 | /* in a product, an acknowledgment in the product documentation would be */ |
26 | /* appreciated but is not required. */ |
27 | /* 2. Altered source versions must be plainly marked as such, and must not */ |
28 | /* be misrepresented as being the original software. */ |
29 | /* 3. This notice may not be removed or altered from any source */ |
30 | /* distribution. */ |
31 | /* */ |
32 | /*****************************************************************************/ |
33 | |
34 | |
35 | |
36 | #include <string.h> |
37 | |
38 | /* common */ |
39 | #include "check.h" |
40 | #include "xmalloc.h" |
41 | |
42 | /* ld65 */ |
43 | #include "error.h" |
44 | #include "exports.h" |
45 | #include "fileinfo.h" |
46 | #include "library.h" |
47 | #include "objdata.h" |
48 | #include "spool.h" |
49 | |
50 | |
51 | |
52 | /*****************************************************************************/ |
53 | /* Data */ |
54 | /*****************************************************************************/ |
55 | |
56 | |
57 | |
58 | /* Collection containing used ObjData objects */ |
59 | Collection ObjDataList = STATIC_COLLECTION_INITIALIZER; |
60 | |
61 | |
62 | |
63 | /*****************************************************************************/ |
64 | /* Code */ |
65 | /*****************************************************************************/ |
66 | |
67 | |
68 | |
69 | ObjData* NewObjData (void) |
70 | /* Allocate a new structure on the heap, insert it into the list, return it */ |
71 | { |
72 | /* Allocate memory */ |
73 | ObjData* O = xmalloc (sizeof (ObjData)); |
74 | |
75 | /* Initialize the data */ |
76 | O->Next = 0; |
77 | O->Name = INVALID_STRING_ID; |
78 | O->Lib = 0; |
79 | O->MTime = 0; |
80 | O->Start = 0; |
81 | O->Flags = 0; |
82 | O->HLLSymBaseId = 0; |
83 | O->SymBaseId = 0; |
84 | O->ScopeBaseId = 0; |
85 | O->SpanBaseId = 0; |
86 | O->Files = EmptyCollection; |
87 | O->Sections = EmptyCollection; |
88 | O->Exports = EmptyCollection; |
89 | O->Imports = EmptyCollection; |
90 | O->DbgSyms = EmptyCollection; |
91 | O->HLLDbgSyms = EmptyCollection; |
92 | O->LineInfos = EmptyCollection; |
93 | O->StringCount = 0; |
94 | O->Strings = 0; |
95 | O->Assertions = EmptyCollection; |
96 | O->Scopes = EmptyCollection; |
97 | O->Spans = EmptyCollection; |
98 | |
99 | /* Return the new entry */ |
100 | return O; |
101 | } |
102 | |
103 | |
104 | |
105 | void FreeObjData (ObjData* O) |
106 | /* Free an ObjData object. NOTE: This function works only for unused object |
107 | ** data, that is, ObjData objects that aren't used because they aren't |
108 | ** referenced. |
109 | */ |
110 | { |
111 | unsigned I; |
112 | |
113 | for (I = 0; I < CollCount (&O->Files); ++I) { |
114 | CollDeleteItem (&((FileInfo*) CollAtUnchecked (&O->Files, I))->Modules, O); |
115 | } |
116 | DoneCollection (&O->Files); |
117 | DoneCollection (&O->Sections); |
118 | for (I = 0; I < CollCount (&O->Exports); ++I) { |
119 | FreeExport (CollAtUnchecked (&O->Exports, I)); |
120 | } |
121 | DoneCollection (&O->Exports); |
122 | for (I = 0; I < CollCount (&O->Imports); ++I) { |
123 | FreeImport (CollAtUnchecked (&O->Imports, I)); |
124 | } |
125 | DoneCollection (&O->Imports); |
126 | DoneCollection (&O->DbgSyms); |
127 | DoneCollection (&O->HLLDbgSyms); |
128 | |
129 | for (I = 0; I < CollCount (&O->LineInfos); ++I) { |
130 | FreeLineInfo (CollAtUnchecked (&O->LineInfos, I)); |
131 | } |
132 | DoneCollection (&O->LineInfos); |
133 | xfree (O->Strings); |
134 | DoneCollection (&O->Assertions); |
135 | DoneCollection (&O->Scopes); |
136 | for (I = 0; I < CollCount (&O->Spans); ++I) { |
137 | FreeSpan (CollAtUnchecked (&O->Spans, I)); |
138 | } |
139 | DoneCollection (&O->Spans); |
140 | |
141 | xfree (O); |
142 | } |
143 | |
144 | |
145 | |
146 | void FreeObjStrings (ObjData* O) |
147 | /* Free the module string data. Used once the object file is loaded completely |
148 | ** when all strings are converted to global strings. |
149 | */ |
150 | { |
151 | xfree (O->Strings); |
152 | O->Strings = 0; |
153 | } |
154 | |
155 | |
156 | |
157 | void InsertObjData (ObjData* O) |
158 | /* Insert the ObjData object into the collection of used ObjData objects. */ |
159 | { |
160 | CollAppend (&ObjDataList, O); |
161 | } |
162 | |
163 | |
164 | |
165 | void InsertObjGlobals (ObjData* O) |
166 | /* Insert imports and exports from the object file into the global import and |
167 | ** export lists. |
168 | */ |
169 | { |
170 | unsigned I; |
171 | |
172 | /* Insert exports and imports */ |
173 | for (I = 0; I < CollCount (&O->Exports); ++I) { |
174 | InsertExport (CollAt (&O->Exports, I)); |
175 | } |
176 | for (I = 0; I < CollCount (&O->Imports); ++I) { |
177 | InsertImport (CollAt (&O->Imports, I)); |
178 | } |
179 | } |
180 | |
181 | |
182 | |
183 | unsigned MakeGlobalStringId (const ObjData* O, unsigned Index) |
184 | /* Convert a local string id into a global one and return it. */ |
185 | { |
186 | if (Index >= O->StringCount) { |
187 | Error ("Invalid string index (%u) in module '%s'" , |
188 | Index, GetObjFileName (O)); |
189 | } |
190 | return O->Strings[Index]; |
191 | } |
192 | |
193 | |
194 | |
195 | const char* GetObjFileName (const ObjData* O) |
196 | /* Get the name of the object file. Return "[linker generated]" if the object |
197 | ** file is NULL. |
198 | */ |
199 | { |
200 | return O? GetString (O->Name) : "[linker generated]" ; |
201 | } |
202 | |
203 | |
204 | |
205 | const struct StrBuf* GetObjString (const ObjData* Obj, unsigned Id) |
206 | /* Get a string from an object file checking for an invalid index */ |
207 | { |
208 | return GetStrBuf (MakeGlobalStringId (Obj, Id)); |
209 | } |
210 | |
211 | |
212 | |
213 | struct Section* GetObjSection (const ObjData* O, unsigned Id) |
214 | /* Get a section from an object file checking for a valid index */ |
215 | { |
216 | if (Id >= CollCount (&O->Sections)) { |
217 | Error ("Invalid section index (%u) in module '%s'" , |
218 | Id, GetObjFileName (O)); |
219 | } |
220 | return CollAtUnchecked (&O->Sections, Id); |
221 | } |
222 | |
223 | |
224 | |
225 | struct Import* GetObjImport (const ObjData* O, unsigned Id) |
226 | /* Get an import from an object file checking for a valid index */ |
227 | { |
228 | if (Id >= CollCount (&O->Imports)) { |
229 | Error ("Invalid import index (%u) in module '%s'" , |
230 | Id, GetObjFileName (O)); |
231 | } |
232 | return CollAtUnchecked (&O->Imports, Id); |
233 | } |
234 | |
235 | |
236 | |
237 | struct Export* GetObjExport (const ObjData* O, unsigned Id) |
238 | /* Get an export from an object file checking for a valid index */ |
239 | { |
240 | if (Id >= CollCount (&O->Exports)) { |
241 | Error ("Invalid export index (%u) in module '%s'" , |
242 | Id, GetObjFileName (O)); |
243 | } |
244 | return CollAtUnchecked (&O->Exports, Id); |
245 | } |
246 | |
247 | |
248 | |
249 | struct DbgSym* GetObjDbgSym (const ObjData* O, unsigned Id) |
250 | /* Get a debug symbol from an object file checking for a valid index */ |
251 | { |
252 | if (Id >= CollCount (&O->DbgSyms)) { |
253 | Error ("Invalid debug symbol index (%u) in module '%s'" , |
254 | Id, GetObjFileName (O)); |
255 | } |
256 | return CollAtUnchecked (&O->DbgSyms, Id); |
257 | } |
258 | |
259 | |
260 | |
261 | struct Scope* GetObjScope (const ObjData* O, unsigned Id) |
262 | /* Get a scope from an object file checking for a valid index */ |
263 | { |
264 | if (Id >= CollCount (&O->Scopes)) { |
265 | Error ("Invalid scope index (%u) in module '%s'" , |
266 | Id, GetObjFileName (O)); |
267 | } |
268 | return CollAtUnchecked (&O->Scopes, Id); |
269 | } |
270 | |
271 | |
272 | |
273 | unsigned ObjDataCount (void) |
274 | /* Return the total number of modules */ |
275 | { |
276 | return CollCount (&ObjDataList); |
277 | } |
278 | |
279 | |
280 | |
281 | void PrintDbgModules (FILE* F) |
282 | /* Output the modules to a debug info file */ |
283 | { |
284 | unsigned I; |
285 | |
286 | /* Output modules */ |
287 | for (I = 0; I < CollCount (&ObjDataList); ++I) { |
288 | |
289 | /* Get this object file */ |
290 | const ObjData* O = CollConstAt (&ObjDataList, I); |
291 | |
292 | /* The main source file is the one at index zero */ |
293 | const FileInfo* Source = CollConstAt (&O->Files, 0); |
294 | |
295 | /* Output the module line */ |
296 | fprintf (F, |
297 | "mod\tid=%u,name=\"%s\",file=%u" , |
298 | I, |
299 | GetObjFileName (O), |
300 | Source->Id); |
301 | |
302 | /* Add library if any */ |
303 | if (O->Lib != 0) { |
304 | fprintf (F, ",lib=%u" , GetLibId (O->Lib)); |
305 | } |
306 | |
307 | /* Terminate the output line */ |
308 | fputc ('\n', F); |
309 | } |
310 | |
311 | } |
312 | |