]> git.sur5r.net Git - cc65/blob - src/ld65/dbgsyms.c
Add the parent scope/symbol to the debug symbol attributes.
[cc65] / src / ld65 / dbgsyms.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                 dbgsyms.c                                 */
4 /*                                                                           */
5 /*                 Debug symbol handling 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 "addrsize.h"
40 #include "check.h"
41 #include "symdefs.h"
42 #include "xmalloc.h"
43
44 /* ld65 */
45 #include "dbgsyms.h"
46 #include "error.h"
47 #include "expr.h"
48 #include "fileio.h"
49 #include "global.h"
50 #include "lineinfo.h"
51 #include "objdata.h"
52 #include "spool.h"
53
54
55
56 /*****************************************************************************/
57 /*                                   Data                                    */
58 /*****************************************************************************/
59
60
61
62 /* We will collect all debug symbols in the following array and remove
63  * duplicates before outputing them.
64  */
65 static DbgSym*  DbgSymPool[256];
66
67
68
69 /*****************************************************************************/
70 /*                                   Code                                    */
71 /*****************************************************************************/
72
73
74
75 static DbgSym* NewDbgSym (unsigned char Type, unsigned char AddrSize, ObjData* O)
76 /* Create a new DbgSym and return it */
77 {
78     /* Allocate memory */
79     DbgSym* D    = xmalloc (sizeof (DbgSym));
80
81     /* Initialize the fields */
82     D->Next      = 0;
83     D->Flags     = 0;
84     D->Obj       = O;
85     D->LineInfos = EmptyCollection;
86     D->Expr      = 0;
87     D->Size      = 0;
88     D->Parent.Id = ~0UL;
89     D->Name      = 0;
90     D->Type      = Type;
91     D->AddrSize  = AddrSize;
92
93     /* Return the new entry */
94     return D;
95 }
96
97
98
99 static DbgSym* GetDbgSym (DbgSym* D, long Val)
100 /* Check if we find the same debug symbol in the table. If we find it, return
101  * a pointer to the other occurrence, if we didn't find it, return NULL.
102  */
103 {
104     /* Create the hash. We hash over the symbol value */
105     unsigned Hash = ((Val >> 24) & 0xFF) ^
106                     ((Val >> 16) & 0xFF) ^
107                     ((Val >>  8) & 0xFF) ^
108                     ((Val >>  0) & 0xFF);
109
110     /* Check for this symbol */
111     DbgSym* Sym = DbgSymPool[Hash];
112     while (Sym) {
113         /* Is this symbol identical? */
114         if (Sym->Name == D->Name && EqualExpr (Sym->Expr, D->Expr)) {
115             /* Found */
116             return Sym;
117         }
118
119         /* Next symbol */
120         Sym = Sym->Next;
121     }
122
123     /* This is the first symbol of it's kind */
124     return 0;
125 }
126
127
128
129 static void InsertDbgSym (DbgSym* D, long Val)
130 /* Insert the symbol into the hashed symbol pool */
131 {
132     /* Create the hash. We hash over the symbol value */
133     unsigned Hash = ((Val >> 24) & 0xFF) ^
134                     ((Val >> 16) & 0xFF) ^
135                     ((Val >>  8) & 0xFF) ^
136                     ((Val >>  0) & 0xFF);
137
138     /* Insert the symbol */
139     D->Next = DbgSymPool [Hash];
140     DbgSymPool [Hash] = D;
141 }
142
143
144
145 DbgSym* ReadDbgSym (FILE* F, ObjData* O)
146 /* Read a debug symbol from a file, insert and return it */
147 {
148     /* Read the type and address size */
149     unsigned Type = ReadVar (F);
150     unsigned char AddrSize = Read8 (F);
151
152     /* Create a new debug symbol */
153     DbgSym* D = NewDbgSym (Type, AddrSize, O);
154
155     /* Read the id of the owner scope/symbol */
156     D->Parent.Id = ReadVar (F);
157
158     /* Read and assign the name */
159     D->Name = MakeGlobalStringId (O, ReadVar (F));
160
161     /* Read the value */
162     if (SYM_IS_EXPR (D->Type)) {
163         D->Expr = ReadExpr (F, O);
164     } else {
165         D->Expr = LiteralExpr (Read32 (F), O);
166     }
167
168     /* Read the size */
169     if (SYM_HAS_SIZE (D->Type)) {
170         D->Size = ReadVar (F);
171     }
172
173     /* Last is the list of line infos for this symbol */
174     ReadLineInfoList (F, O, &D->LineInfos);
175
176     /* Return the new DbgSym */
177     return D;
178 }
179
180
181
182 void ClearDbgSymTable (void)
183 /* Clear the debug symbol table */
184 {
185     unsigned I;
186     for (I = 0; I < sizeof (DbgSymPool) / sizeof (DbgSymPool[0]); ++I) {
187         DbgSym* Sym = DbgSymPool[I];
188         DbgSymPool[I] = 0;
189         while (Sym) {
190             DbgSym* NextSym = Sym->Next;
191             Sym->Next = 0;
192             Sym = NextSym;
193         }
194     }
195 }
196
197
198
199 long GetDbgSymVal (const DbgSym* D)
200 /* Get the value of this symbol */
201 {
202     CHECK (D->Expr != 0);
203     return GetExprVal (D->Expr);
204 }
205
206
207
208 void PrintDbgSyms (ObjData* O, FILE* F)
209 /* Print the debug symbols in a debug file */
210 {
211     unsigned I;
212
213     /* Walk through all debug symbols in this module */
214     for (I = 0; I < CollCount (&O->DbgSyms); ++I) {
215
216         long Val;
217
218         /* Get the next debug symbol */
219         DbgSym* S = CollAt (&O->DbgSyms, I);
220
221         /* Get the symbol value */
222         Val = GetDbgSymVal (S);
223
224         /* Lookup this symbol in the table. If it is found in the table, it was
225          * already written to the file, so don't emit it twice. If it is not in
226          * the table, insert and output it.
227          */
228         if (GetDbgSym (S, Val) == 0) {
229
230             SegExprDesc D;
231
232             /* Emit the base data for the entry */
233             fprintf (F,
234                      "sym\tname=\"%s\",value=0x%lX,addrsize=%s,type=%s",
235                      GetString (S->Name),
236                      Val,
237                      AddrSizeToStr (S->AddrSize),
238                      SYM_IS_LABEL (S->Type)? "label" : "equate");
239
240             /* Emit the size only if we know it */
241             if (S->Size != 0) {
242                 fprintf (F, ",size=%lu", S->Size);
243             }
244
245             /* Check for a segmented expression and add the segment id to the
246              * debug info if we have one.
247              */
248             GetSegExprVal (S->Expr, &D);
249             if (!D.TooComplex && D.Seg != 0) {
250                 fprintf (F, ",segment=%u", D.Seg->Id);
251             }
252
253             /* Terminate the output line */
254             fputc ('\n', F);
255
256             /* Insert the symbol into the table */
257             InsertDbgSym (S, Val);
258         }
259     }
260 }
261
262
263
264 void PrintDbgSymLabels (ObjData* O, FILE* F)
265 /* Print the debug symbols in a VICE label file */
266 {
267     unsigned I;
268
269     /* Walk through all debug symbols in this module */
270     for (I = 0; I < CollCount (&O->DbgSyms); ++I) {
271
272         long Val;
273
274         /* Get the next debug symbol */
275         DbgSym* D = CollAt (&O->DbgSyms, I);
276
277         /* Emit this symbol only if it is a label (ignore equates) */
278         if (SYM_IS_EQUATE (D->Type)) {
279             continue;
280         }
281
282         /* Get the symbol value */
283         Val = GetDbgSymVal (D);
284
285         /* Lookup this symbol in the table. If it is found in the table, it was
286          * already written to the file, so don't emit it twice. If it is not in
287          * the table, insert and output it.
288          */
289         if (GetDbgSym (D, Val) == 0) {
290
291             /* Emit the VICE label line */
292             fprintf (F, "al %06lX .%s\n", Val, GetString (D->Name));
293
294             /* Insert the symbol into the table */
295             InsertDbgSym (D, Val);
296         }
297     }
298 }
299
300
301
302