1 /* Copyright (c) 2019-2019, David Anderson
2 All rights reserved.
3
4 Redistribution and use in source and binary forms, with
5 or without modification, are permitted provided that the
6 following conditions are met:
7
8 Redistributions of source code must retain the above
9 copyright notice, this list of conditions and the following
10 disclaimer.
11
12 Redistributions in binary form must reproduce the above
13 copyright notice, this list of conditions and the following
14 disclaimer in the documentation and/or other materials
15 provided with the distribution.
16
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
18 CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
19 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
22 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
29 EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include "config.h"
33 #include "libdwarfdefs.h"
34 #include <stdio.h>
35 #include <string.h>
36 #include <stddef.h>
37 #ifdef HAVE_STDINT_H
38 #include <stdint.h> /* For uintptr_t */
39 #endif /* HAVE_STDINT_H */
40 #include "pro_incl.h"
41 #include "dwarf.h"
42 #include "libdwarf.h"
43 #include "pro_opaque.h"
44 #include "dwarfstring.h"
45
46
47
48
49 /* in the producer_init extras string.
50 Handles hex and decimal. Not octal.
51 Used a very small number of times, so performance
52 not an issue. */
53
54 /* err will be used...shortly */
55 static int
translatetosigned(char * s,Dwarf_Signed * v,UNUSEDARG int * err)56 translatetosigned(char *s,Dwarf_Signed *v, UNUSEDARG int *err)
57 {
58 unsigned char *cp = (unsigned char *)s;
59 unsigned char *digits = (unsigned char *)s;
60 int signmult = 1;
61 Dwarf_Signed l = 0;
62
63 if (*cp == '0' &&
64 (*(cp+1) == 'x'|| (*(cp+1) == 'X'))) {
65 digits += 2;
66 cp = digits;
67 for( ; *cp; cp++) {
68 l = l << 4;
69 switch (*cp) {
70 case '0':
71 case '1':
72 case '2':
73 case '3':
74 case '4':
75 case '5':
76 case '6':
77 case '7':
78 case '8':
79 case '9':
80 l += (*cp - '0');
81 break;
82 case 'a':
83 case 'A':
84 l += 10;
85 break;
86 case 'b':
87 case 'B':
88 l += 11;
89 break;
90 case 'c':
91 case 'C':
92 l += 12;
93 break;
94 case 'd':
95 case 'D':
96 l += 13;
97 break;
98 case 'e':
99 case 'E':
100 l += 14;
101 break;
102 case 'f':
103 case 'F':
104 l += 15;
105 break;
106 default:
107 #ifdef TESTING
108 printf("ERROR in hex string \"%s\" "
109 "bad character 0x%x, line %d %s\n",
110 s,*cp,__LINE__,__FILE__);
111 #endif
112 *err = DW_DLE_HEX_STRING_ERROR;
113 return DW_DLV_ERROR;
114 }
115 }
116 *v = l;
117 return DW_DLV_OK;
118 } else if (*cp == '-') {
119 signmult = -1;
120 digits ++;
121 }
122
123 cp = digits;
124 for( ; *cp; cp++) {
125 l = l * 10;
126 switch (*cp) {
127 case '9':
128 case '8':
129 case '7':
130 case '6':
131 case '5':
132 case '4':
133 case '3':
134 case '2':
135 case '1':
136 case '0':
137 l += (*cp - '0');
138 break;
139 default:
140 #ifdef TESTING
141 printf("ERROR in decimal string \"%s\", "
142 "bad character 0x%x, line %d %s\n",
143 s,*cp,__LINE__,__FILE__);
144 #endif
145 *err = DW_DLE_DECIMAL_STRING_ERROR;
146 return DW_DLV_ERROR;
147 }
148 }
149 *v = signmult * l;
150 return DW_DLV_OK;
151 }
152
153 static int
update_named_field(Dwarf_P_Debug dbg,dwarfstring * cmsname,dwarfstring * cmsvalue,int * err)154 update_named_field(Dwarf_P_Debug dbg, dwarfstring *cmsname,dwarfstring *cmsvalue,
155 int *err)
156 {
157 char *name = dwarfstring_string(cmsname);
158 char *value = dwarfstring_string(cmsvalue);
159 Dwarf_Signed v = 0;
160 int res;
161
162 res = translatetosigned(value,&v,err);
163 if (res != DW_DLV_OK) {
164 return res;
165 }
166 if ( dwarfstring_strlen(cmsvalue) == 0) {
167 return DW_DLV_NO_ENTRY;
168 }
169
170 /* The value in the string is a number,
171 but always quite a small number. */
172 if (!strcmp(name,"default_is_stmt")) {
173 dbg->de_line_inits.pi_default_is_stmt = (unsigned)v;
174 } else if (!strcmp(name,"minimum_instruction_length")) {
175 dbg->de_line_inits.pi_minimum_instruction_length = (unsigned)v;
176 } else if (!strcmp(name,"maximum_operations_per_instruction")) {
177 dbg->de_line_inits.pi_maximum_operations_per_instruction = (unsigned)v;
178 } else if (!strcmp(name,"opcode_base")) {
179 dbg->de_line_inits.pi_opcode_base = (unsigned)v;
180 } else if (!strcmp(name,"line_base")) {
181 dbg->de_line_inits.pi_line_base = (int)v;
182 } else if (!strcmp(name,"line_range")) {
183 dbg->de_line_inits.pi_line_range = (int)v;
184 } else if (!strcmp(name,"linetable_version")) {
185 dbg->de_line_inits.pi_linetable_version = (unsigned)v;
186 dbg->de_output_version = (unsigned)v;
187 } else if (!strcmp(name,"segment_selector_size")) {
188 dbg->de_line_inits.pi_segment_selector_size = (unsigned)v;
189 } else if (!strcmp(name,"segment_size")) {
190 dbg->de_line_inits.pi_segment_size = (unsigned)v;
191 } else if (!strcmp(name,"address_size")) {
192 dbg->de_line_inits.pi_address_size = (unsigned)v;
193 dbg->de_pointer_size = (unsigned)v;
194 } else {
195 #ifdef TESTING
196 printf("ERROR due to unknown string \"%s\", line %d %s\n",
197 name,__LINE__,__FILE__);
198 #endif
199 *err = DW_DLE_PRO_INIT_EXTRAS_UNKNOWN;
200 return DW_DLV_ERROR;
201 }
202 return DW_DLV_OK;
203 }
204 static int
update_named_value(Dwarf_P_Debug dbg,dwarfstring * cms,int * err)205 update_named_value(Dwarf_P_Debug dbg, dwarfstring*cms,
206 int *err)
207 {
208 char * str = dwarfstring_string(cms);
209 char *cp = str;
210 char * value_start = 0;
211 dwarfstring cmsname;
212 dwarfstring cmsvalue;
213 unsigned slen = 0;
214 int res = 0;
215
216 dwarfstring_constructor(&cmsname);
217 dwarfstring_constructor(&cmsvalue);
218 for ( ; *cp && *cp != '=' && *cp != ' '; cp++) { }
219 if (! *cp) {
220 /* Ignore this, it's empty or has no =value clause */
221 dwarfstring_destructor(&cmsname);
222 dwarfstring_destructor(&cmsvalue);
223 /* FIXME *err */
224 return DW_DLV_NO_ENTRY;
225 }
226 if (*cp == ' ') {
227 /* Trailing spaces, no = is an input bug. */
228 dwarfstring_destructor(&cmsname);
229 dwarfstring_destructor(&cmsvalue);
230 #ifdef TESTING
231 printf("ERROR due to trailing spaces before = in \"%s\", line %d %s\n",
232 cp,__LINE__,__FILE__);
233 #endif
234 *err = DW_DLE_PRO_INIT_EXTRAS_ERR;
235 return DW_DLV_ERROR;
236 }
237 slen = cp - str;
238 dwarfstring_append_length(&cmsname,str,slen);
239 cp++;
240 value_start = cp;
241 for ( ; *cp && *cp != ' '; cp++) { }
242 slen = cp - value_start;
243 if (slen) {
244 dwarfstring_append_length(&cmsvalue,value_start,slen);
245 } else {
246 dwarfstring_destructor(&cmsname);
247 dwarfstring_destructor(&cmsvalue);
248 return DW_DLV_NO_ENTRY;
249 }
250 res = update_named_field(dbg,&cmsname,&cmsvalue,err);
251 dwarfstring_destructor(&cmsname);
252 dwarfstring_destructor(&cmsvalue);
253 return res;
254 }
255
256 static int
find_next_comma(const char * base,const char ** nextcomma)257 find_next_comma(const char *base,const char **nextcomma)
258 {
259 const char *cp = base;
260 for( ; *cp ; ++cp) {
261 if (*cp == ',') {
262 *nextcomma = cp;
263 return DW_DLV_OK;
264 }
265 }
266 /* Encountered end of string, should not happen as
267 we ensured a last string. */
268 *nextcomma = cp;
269 return DW_DLV_OK;
270 }
271
272 /* Publicly visible in in libdwarf to enable easy testing
273 of the code here. */
274 int
_dwarf_log_extra_flagstrings(Dwarf_P_Debug dbg,const char * extra,int * err)275 _dwarf_log_extra_flagstrings(Dwarf_P_Debug dbg,
276 const char *extra,
277 int *err)
278 {
279 int res = 0;
280 const char *nextcharloc = 0;
281 const char *nextcomma = 0;
282 dwarfstring cms;
283 dwarfstring input;
284
285 if (!extra || !*extra) {
286 /* Nothing to do. */
287 return DW_DLV_NO_ENTRY;
288 }
289
290 dwarfstring_constructor(&cms);
291 dwarfstring_constructor(&input);
292 dwarfstring_append(&input,(char *)extra);
293 /* Adding a final , simplifies logic here. */
294 dwarfstring_append(&input,(char *)",");
295 nextcharloc = dwarfstring_string(&input);
296 while (1) {
297 dwarfstring_reset(&cms);
298 find_next_comma(nextcharloc,&nextcomma);
299 {
300 unsigned len = nextcomma - nextcharloc;
301 if (len > 0) {
302 dwarfstring_append_length(&cms,(char *)nextcharloc,
303 len);
304 res = update_named_value(dbg,&cms,err);
305 if (res == DW_DLV_ERROR) {
306 dwarfstring_destructor(&cms);
307 dwarfstring_destructor(&input);
308 return res;
309 }
310 } else {/* else empty, */
311 }
312 if (!(nextcomma[1])) {
313 dwarfstring_destructor(&cms);
314 dwarfstring_destructor(&input);
315 return DW_DLV_OK;
316 }
317 nextcharloc = nextcomma+1;
318 }
319 }
320 dwarfstring_destructor(&input);
321 dwarfstring_destructor(&cms);
322 return DW_DLV_OK;
323 }
324
325 /* ===== end Initialization using string=value,string2=valu2 (etc) */
326