1 | /*****************************************************************************/ |
2 | /* */ |
3 | /* span.c */ |
4 | /* */ |
5 | /* A span of data within a segment */ |
6 | /* */ |
7 | /* */ |
8 | /* */ |
9 | /* (C) 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 | /* common */ |
37 | #include "gentype.h" |
38 | #include "xmalloc.h" |
39 | |
40 | /* ld65 */ |
41 | #include "fileio.h" |
42 | #include "objdata.h" |
43 | #include "segments.h" |
44 | #include "span.h" |
45 | #include "tpool.h" |
46 | |
47 | |
48 | |
49 | /*****************************************************************************/ |
50 | /* Data */ |
51 | /*****************************************************************************/ |
52 | |
53 | |
54 | |
55 | /* Definition of a span */ |
56 | struct Span { |
57 | unsigned Id; /* Id of the span */ |
58 | unsigned Sec; /* Section id of this span */ |
59 | unsigned long Offs; /* Offset of span within segment */ |
60 | unsigned long Size; /* Size of span */ |
61 | unsigned Type; /* Generic type of the data */ |
62 | }; |
63 | |
64 | |
65 | |
66 | /*****************************************************************************/ |
67 | /* Code */ |
68 | /*****************************************************************************/ |
69 | |
70 | |
71 | |
72 | static Span* NewSpan (unsigned Id) |
73 | /* Create and return a new span */ |
74 | { |
75 | /* Allocate memory */ |
76 | Span* S = xmalloc (sizeof (Span)); |
77 | |
78 | /* Initialize the fields as necessary */ |
79 | S->Id = Id; |
80 | |
81 | /* Return the result */ |
82 | return S; |
83 | } |
84 | |
85 | |
86 | |
87 | Span* ReadSpan (FILE* F, ObjData* O, unsigned Id) |
88 | /* Read a Span from a file and return it */ |
89 | { |
90 | unsigned Type; |
91 | |
92 | /* Create a new Span and initialize it */ |
93 | Span* S = NewSpan (Id); |
94 | S->Sec = ReadVar (F); |
95 | S->Offs = ReadVar (F); |
96 | S->Size = ReadVar (F); |
97 | |
98 | /* Read the type. An id of zero means an empty string (no need to check) */ |
99 | Type = ReadVar (F); |
100 | if (Type == 0) { |
101 | S->Type = INVALID_TYPE_ID; |
102 | } else { |
103 | S->Type = GetTypeId (GetObjString (O, Type)); |
104 | } |
105 | |
106 | /* Return the new span */ |
107 | return S; |
108 | } |
109 | |
110 | |
111 | |
112 | unsigned* ReadSpanList (FILE* F) |
113 | /* Read a list of span ids from a file. The list is returned as an array of |
114 | ** unsigneds, the first being the number of spans (never zero) followed by |
115 | ** the span ids. If the number of spans is zero, NULL is returned. |
116 | */ |
117 | { |
118 | unsigned* Spans; |
119 | |
120 | /* First is number of Spans */ |
121 | unsigned Count = ReadVar (F); |
122 | if (Count == 0) { |
123 | return 0; |
124 | } |
125 | |
126 | /* Allocate memory for the list and set the count */ |
127 | Spans = xmalloc ((Count + 1) * sizeof (*Spans)); |
128 | *Spans = Count; |
129 | |
130 | /* Read the spans and add them */ |
131 | while (Count) { |
132 | Spans[Count] = ReadVar (F); |
133 | --Count; |
134 | } |
135 | |
136 | /* Return the list */ |
137 | return Spans; |
138 | } |
139 | |
140 | |
141 | |
142 | unsigned* DupSpanList (const unsigned* S) |
143 | /* Duplicate a span list */ |
144 | { |
145 | unsigned Size; |
146 | |
147 | /* The list may be empty */ |
148 | if (S == 0) { |
149 | return 0; |
150 | } |
151 | |
152 | /* Allocate memory, copy and return the new list */ |
153 | Size = (*S + 1) * sizeof (*S); |
154 | return memcpy (xmalloc (Size), S, Size); |
155 | } |
156 | |
157 | |
158 | |
159 | void FreeSpan (Span* S) |
160 | /* Free a span structure */ |
161 | { |
162 | /* Just free the structure */ |
163 | xfree (S); |
164 | } |
165 | |
166 | |
167 | |
168 | unsigned SpanCount (void) |
169 | /* Return the total number of spans */ |
170 | { |
171 | /* Walk over all object files */ |
172 | unsigned I; |
173 | unsigned Count = 0; |
174 | for (I = 0; I < CollCount (&ObjDataList); ++I) { |
175 | |
176 | /* Get this object file */ |
177 | const ObjData* O = CollAtUnchecked (&ObjDataList, I); |
178 | |
179 | /* Count spans */ |
180 | Count += CollCount (&O->Spans); |
181 | } |
182 | |
183 | return Count; |
184 | } |
185 | |
186 | |
187 | |
188 | void PrintDbgSpanList (FILE* F, const ObjData* O, const unsigned* List) |
189 | /* Output a string ",span=x[+y...]" for the given list. If the list is empty |
190 | ** or NULL, output nothing. This is a helper function for other modules to |
191 | ** print a list of spans read by ReadSpanList to the debug info file. |
192 | */ |
193 | { |
194 | if (List && *List) { |
195 | unsigned I; |
196 | const char* Format = ",span=%u" ; |
197 | for (I = 0; I < *List; ++I) { |
198 | fprintf (F, Format, O->SpanBaseId + List[I+1]); |
199 | Format = "+%u" ; |
200 | } |
201 | } |
202 | } |
203 | |
204 | |
205 | |
206 | void PrintDbgSpans (FILE* F) |
207 | /* Output the spans to a debug info file */ |
208 | { |
209 | unsigned I, J; |
210 | StrBuf SpanType = STATIC_STRBUF_INITIALIZER; |
211 | |
212 | |
213 | /* Walk over all object files */ |
214 | for (I = 0; I < CollCount (&ObjDataList); ++I) { |
215 | |
216 | /* Get this object file */ |
217 | ObjData* O = CollAtUnchecked (&ObjDataList, I); |
218 | |
219 | /* Walk over all spans in this object file */ |
220 | for (J = 0; J < CollCount (&O->Spans); ++J) { |
221 | |
222 | /* Get this span */ |
223 | const Span* S = CollAtUnchecked (&O->Spans, J); |
224 | |
225 | /* Get the section for this span */ |
226 | const Section* Sec = GetObjSection (O, S->Sec); |
227 | |
228 | /* Output the data */ |
229 | fprintf (F, "span\tid=%u,seg=%u,start=%lu,size=%lu" , |
230 | O->SpanBaseId + S->Id, |
231 | Sec->Seg->Id, |
232 | Sec->Offs + S->Offs, |
233 | S->Size); |
234 | |
235 | /* If we have a type, add it */ |
236 | if (S->Type != INVALID_TYPE_ID) { |
237 | fprintf (F, ",type=%u" , S->Type); |
238 | } |
239 | |
240 | /* Terminate the output line */ |
241 | fputc ('\n', F); |
242 | } |
243 | } |
244 | |
245 | /* Free the string buffer */ |
246 | SB_Done (&SpanType); |
247 | } |
248 | |