xref: /illumos-gate/usr/src/lib/libdwarf/common/dwarf_macro5.c (revision ed093b41a93e8563e6e1e5dae0768dda2a7bcc27)
1 /*
2   Copyright (C) 2015-2019 David Anderson. All Rights Reserved.
3 
4   This program is free software; you can redistribute it and/or modify it
5   under the terms of version 2.1 of the GNU Lesser General Public License
6   as published by the Free Software Foundation.
7 
8   This program is distributed in the hope that it would be useful, but
9   WITHOUT ANY WARRANTY; without even the implied warranty of
10   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 
12   Further, this software is distributed without any warranty that it is
13   free of the rightful claim of any third person regarding infringement
14   or the like.  Any license provided herein, whether implied or
15   otherwise, applies only to this software file.  Patent licenses, if
16   any, provided herein do not apply to combinations of this program with
17   other software, or any other product whatsoever.
18 
19   You should have received a copy of the GNU Lesser General Public
20   License along with this program; if not, write the Free Software
21   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
22   USA.
23 
24 */
25 
26 #include "config.h"
27 #include <stdio.h>
28 #include <limits.h>
29 #ifdef HAVE_STDLIB_H
30 #include <stdlib.h>
31 #endif /* HAVE_STDLIB_H */
32 #ifdef HAVE_MALLOC_H
33 /* Useful include for some Windows compilers. */
34 #include <malloc.h>
35 #endif /* HAVE_MALLOC_H */
36 #include "dwarf_incl.h"
37 #include "dwarf_alloc.h"
38 #include "dwarf_error.h"
39 #include "dwarf_util.h"
40 #include "dwarf_macro5.h"
41 
42 #define TRUE 1
43 #define FALSE 0
44 
45 /*  Section 6.3: Macro Information:
46     Each macro unit ends with an entry
47     containing an opcode of 0. */
48 
49 static const Dwarf_Small dwarf_udata_string_form[]  = {DW_FORM_udata,DW_FORM_string};
50 static const Dwarf_Small dwarf_udata_udata_form[]   = {DW_FORM_udata,DW_FORM_udata};
51 static const Dwarf_Small dwarf_udata_strp_form[]    = {DW_FORM_udata,DW_FORM_strp};
52 static const Dwarf_Small dwarf_udata_strp_sup_form[] = {DW_FORM_udata,DW_FORM_strp_sup};
53 static const Dwarf_Small dwarf_secoffset_form[]     = {DW_FORM_sec_offset};
54 static const Dwarf_Small dwarf_udata_strx_form[]    = {DW_FORM_udata,DW_FORM_strx};
55 
56 struct Dwarf_Macro_Forms_s dw5formsarray[] = {
57     {0,0,0},
58     {DW_MACRO_define,2,dwarf_udata_string_form},
59     {DW_MACRO_undef,2,dwarf_udata_string_form},
60     {DW_MACRO_start_file,2,dwarf_udata_udata_form},
61     {DW_MACRO_end_file,0,0},
62 
63     {DW_MACRO_define_strp,2,dwarf_udata_strp_form},
64     {DW_MACRO_undef_strp,2,dwarf_udata_strp_form},
65     {DW_MACRO_import,1,dwarf_secoffset_form},
66 
67     {DW_MACRO_define_sup,2,dwarf_udata_strp_sup_form},
68     {DW_MACRO_undef_sup,2,dwarf_udata_strp_sup_form},
69     {DW_MACRO_import_sup,1,dwarf_secoffset_form},
70 
71     {DW_MACRO_define_strx,2,dwarf_udata_strx_form},
72     {DW_MACRO_undef_strx,2,dwarf_udata_strx_form},
73 };
74 
75 
76 
77 /* Represents DWARF 5 macro info */
78 /* .debug_macro predefined, in order by value  */
79 static const struct Dwarf_Macro_OperationsList_s dwarf_default_macro_opslist = {
80 13, dw5formsarray
81 };
82 
83 
84 static int _dwarf_internal_macro_context_by_offset(Dwarf_Debug dbg,
85     Dwarf_Unsigned offset,
86     Dwarf_Unsigned  * version_out,
87     Dwarf_Macro_Context * macro_context_out,
88     Dwarf_Unsigned *macro_ops_count_out,
89     Dwarf_Unsigned *macro_ops_data_length,
90     char **srcfiles,
91     Dwarf_Signed srcfilescount,
92     const char *comp_dir,
93     const char *comp_name,
94     Dwarf_CU_Context cu_context,
95     Dwarf_Error * error);
96 
97 static int _dwarf_internal_macro_context(Dwarf_Die die,
98     Dwarf_Bool offset_specified,
99     Dwarf_Unsigned offset,
100     Dwarf_Unsigned  * version_out,
101     Dwarf_Macro_Context * macro_context_out,
102     Dwarf_Unsigned *macro_unit_offset_out,
103     Dwarf_Unsigned *macro_ops_count_out,
104     Dwarf_Unsigned *macro_ops_data_length,
105     Dwarf_Error * error);
106 
107 static int
108 is_std_moperator(Dwarf_Small op)
109 {
110     if (op >= 1 && op <= DW_MACRO_undef_strx) {
111         return TRUE;
112     }
113     return FALSE;
114 }
115 
116 static int
117 _dwarf_skim_forms(Dwarf_Debug dbg,
118     Dwarf_Macro_Context mcontext,
119     Dwarf_Small *mdata_start,
120     unsigned formcount,
121     const Dwarf_Small *forms,
122     Dwarf_Small *section_end,
123     Dwarf_Unsigned *forms_length,
124     Dwarf_Error *error)
125 {
126     unsigned i = 0;
127     Dwarf_Small curform = 0 ;
128     Dwarf_Unsigned totallen = 0;
129     Dwarf_Unsigned v = 0;
130     Dwarf_Unsigned ret_value = 0;
131     Dwarf_Unsigned length;
132     Dwarf_Small *mdata = mdata_start;
133     Dwarf_Unsigned leb128_length = 0;
134 
135     for( ; i < formcount; ++i) {
136         curform = forms[i];
137         if (mdata >= section_end) {
138             _dwarf_error(dbg, error, DW_DLE_MACRO_OFFSET_BAD);
139             return DW_DLV_ERROR;
140         }
141         switch(curform) {
142         default:
143             _dwarf_error(dbg,error,
144                 DW_DLE_DEBUG_FORM_HANDLING_INCOMPLETE);
145             return DW_DLV_ERROR;
146         case DW_FORM_block1:
147             v =  *(Dwarf_Small *) mdata;
148             totallen += v+1;
149             mdata += v+1;
150             break;
151         case DW_FORM_block2:
152             READ_UNALIGNED_CK(dbg, ret_value, Dwarf_Unsigned,
153                 mdata, DWARF_HALF_SIZE,
154                 error,section_end);
155             v = ret_value + DWARF_HALF_SIZE;
156             totallen += v;
157             mdata += v;
158             break;
159         case DW_FORM_block4:
160             READ_UNALIGNED_CK(dbg, ret_value, Dwarf_Unsigned,
161                 mdata, DWARF_32BIT_SIZE,
162                 error,section_end);
163             v = ret_value + DWARF_32BIT_SIZE;
164             totallen += v;
165             mdata += v;
166             break;
167         case DW_FORM_data1:
168             v = 1;
169             totallen += v;
170             mdata += v;
171             break;
172         case DW_FORM_data2:
173             v = 2;
174             totallen += v;
175             mdata += v;
176             break;
177         case DW_FORM_data4:
178             v = 4;
179             totallen += v;
180             mdata += v;
181             break;
182         case DW_FORM_data8:
183             v = 8;
184             totallen += v;
185             mdata += v;
186             break;
187         case DW_FORM_data16:
188             v = 8;
189             totallen += v;
190             mdata += v;
191             break;
192         case DW_FORM_string: {
193             int res = _dwarf_check_string_valid(dbg,
194                 mdata,mdata, section_end,
195                 DW_DLE_MACRO_STRING_BAD,error);
196             if(res != DW_DLV_OK) {
197                 return res;
198             }
199             v = strlen((char *) mdata) + 1;
200             totallen += v;
201             mdata += v;
202             }
203             break;
204         case DW_FORM_block:
205             DECODE_LEB128_UWORD_LEN_CK(mdata,length,leb128_length,
206                 dbg, error,section_end);
207             v = length + leb128_length;
208             totallen += v;
209             break;
210         case DW_FORM_flag:
211             v = 1;
212             totallen += v;
213             mdata += v;
214             break;
215         case DW_FORM_sec_offset:
216             /* If 32bit dwarf, is 4. Else is 64bit dwarf and is 8. */
217             v = mcontext->mc_offset_size;
218             totallen += v;
219             mdata += v;
220             break;
221         case DW_FORM_sdata:
222             /*  Discard the decoded value, we just want the length
223                 of the value. */
224             DECODE_LEB128_UWORD_LEN_CK(mdata,length,leb128_length,
225                 dbg, error,section_end);
226             totallen += v;
227             break;
228         case DW_FORM_strx:
229             DECODE_LEB128_UWORD_LEN_CK(mdata,length,leb128_length,
230                 dbg, error,section_end);
231             totallen += leb128_length;;
232             break;
233         case DW_FORM_strp:
234             v = mcontext->mc_offset_size;
235             mdata += v;
236             totallen += v;
237             break;
238         case DW_FORM_udata:
239             /*  Discard the decoded value, we just want the length
240                 of the value. */
241             DECODE_LEB128_UWORD_LEN_CK(mdata,length,leb128_length,
242                 dbg, error,section_end);
243             totallen += leb128_length;
244             break;
245         }
246     }
247     if (mdata > section_end) {
248         _dwarf_error(dbg, error, DW_DLE_MACRO_OFFSET_BAD);
249         return DW_DLV_ERROR;
250     }
251     *forms_length = totallen;
252     return DW_DLV_OK;
253 }
254 
255 #if 0 /* FOR DEBUGGING */
256 static void
257 dump_bytes(Dwarf_Small * start, long len)
258 {
259     Dwarf_Small *end = start + len;
260     Dwarf_Small *cur = start;
261     unsigned pos = 0;
262 
263     printf("dump %ld bytes, start at 0x%lx\n",len,(unsigned long)start);
264     printf("0x");
265     for (; cur < end;pos++, cur++) {
266         if (!(pos %4)) {
267             printf(" ");
268         }
269         printf("%02x",*cur);
270     }
271     printf("\n");
272 }
273 Dwarf_Bool
274 is_defundef(unsigned op)
275 {
276     switch(op){
277     case DW_MACRO_define:
278     case DW_MACRO_undef:
279     case DW_MACRO_define_strp:
280     case DW_MACRO_undef_strp:
281     case DW_MACRO_define_strx:
282     case DW_MACRO_undef_strx:
283     case DW_MACRO_define_sup:
284     case DW_MACRO_undef_sup:
285         return TRUE;
286     }
287     return FALSE;
288 }
289 #endif /* FOR DEBUGGING */
290 
291 
292 /*  On first call (for this macro_context),
293     build_ops_array is FALSE. On second,
294     it is TRUE and we know the count so we allocate and fill in
295     the ops array. */
296 static int
297 _dwarf_get_macro_ops_count_internal(Dwarf_Macro_Context macro_context,
298     Dwarf_Bool build_ops_array,
299     Dwarf_Error *error)
300 {
301     Dwarf_Debug dbg = 0;
302     Dwarf_Small *mdata = 0;
303     Dwarf_Small *section_end = 0;
304     Dwarf_Small *section_base = 0;
305     Dwarf_Unsigned opcount = 0;
306     Dwarf_Unsigned known_ops_count = 0;
307     struct Dwarf_Macro_Operator_s *opsarray = 0;
308     struct Dwarf_Macro_Operator_s *curopsentry = 0;
309     int res = 0;
310 
311     dbg = macro_context->mc_dbg;
312     if (build_ops_array) {
313         known_ops_count = macro_context->mc_macro_ops_count;
314         opsarray = (struct Dwarf_Macro_Operator_s *)
315             calloc(known_ops_count,sizeof(struct Dwarf_Macro_Operator_s));
316         if(!opsarray) {
317             _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
318             return DW_DLV_ERROR;
319         }
320         curopsentry = opsarray;
321         macro_context->mc_ops = opsarray;
322     }
323     section_base = dbg->de_debug_macro.dss_data;
324     section_end = section_base + dbg->de_debug_macro.dss_size;
325     mdata = macro_context->mc_macro_ops;
326 
327     while (mdata < section_end) {
328         Dwarf_Small op = 0;
329 
330         op = *mdata;
331         ++opcount;
332         ++mdata;
333         if (!op) {
334             Dwarf_Unsigned opslen = 0;
335             /*  End of ops, this is terminator, count the ending 0
336                 as an operator so dwarfdump can print it.  */
337             opslen = mdata - macro_context->mc_macro_ops;
338             macro_context->mc_macro_ops_count = opcount;
339             macro_context->mc_ops_data_length = opslen;
340             macro_context->mc_total_length = opslen +
341                 macro_context->mc_macro_header_length;
342             return DW_DLV_OK;
343         }
344         if (is_std_moperator(op)) {
345             struct Dwarf_Macro_Forms_s * ourform =
346                 dw5formsarray + op;
347             /* ASSERT: op == ourform->mf_code */
348             unsigned formcount = ourform->mf_formcount;
349             const Dwarf_Small *forms = ourform->mf_formbytes;
350             Dwarf_Unsigned forms_length = 0;
351 
352             res = _dwarf_skim_forms(dbg,macro_context,mdata,
353                 formcount,forms,
354                 section_end,
355                 &forms_length,error);
356             if ( res != DW_DLV_OK) {
357                 return res;
358             }
359             if(build_ops_array) {
360                 curopsentry->mo_opcode = op;
361                 curopsentry->mo_form = ourform;
362                 curopsentry->mo_data = mdata;
363             }
364             mdata += forms_length;
365         } else {
366             /* FIXME Add support for user defined ops. */
367             _dwarf_error(dbg, error, DW_DLE_MACRO_OP_UNHANDLED);
368             return DW_DLV_ERROR;
369         }
370         if (mdata > section_end)  {
371             _dwarf_error(dbg, error, DW_DLE_MACRO_PAST_END);
372             return DW_DLV_ERROR;
373         }
374         if (build_ops_array) {
375             curopsentry++;
376         }
377     }
378     _dwarf_error(dbg, error, DW_DLE_MACRO_PAST_END);
379     return DW_DLV_ERROR;
380 }
381 
382 int
383 dwarf_get_macro_op(Dwarf_Macro_Context macro_context,
384     Dwarf_Unsigned op_number,
385     Dwarf_Unsigned * op_start_section_offset,
386     Dwarf_Half    * macro_operator,
387     Dwarf_Half    * forms_count,
388     const Dwarf_Small **   formcode_array,
389     Dwarf_Error *error)
390 {
391     struct Dwarf_Macro_Operator_s *curop = 0;
392     Dwarf_Debug dbg = 0;
393     if (!macro_context || macro_context->mc_sentinel != 0xada) {
394         if(macro_context) {
395             dbg = macro_context->mc_dbg;
396         }
397         _dwarf_error(dbg, error,DW_DLE_BAD_MACRO_HEADER_POINTER);
398         return DW_DLV_ERROR;
399     }
400     dbg = macro_context->mc_dbg;
401     if (op_number >= macro_context->mc_macro_ops_count) {
402         _dwarf_error(dbg, error,DW_DLE_BAD_MACRO_INDEX);
403         return DW_DLV_ERROR;
404     }
405     curop = macro_context->mc_ops + op_number;
406 
407     /*  ASSERT: *op_start_section_offset ==
408         (curop->mo_data -1) - dbg->de_debug_macro.dss_data  */
409     *op_start_section_offset =
410         ((curop->mo_data -1) - macro_context->mc_macro_header) +
411         macro_context->mc_section_offset;
412     *macro_operator = curop->mo_opcode;
413     if (curop->mo_form) {
414         *forms_count  = curop->mo_form->mf_formcount;
415         *formcode_array = curop->mo_form->mf_formbytes;
416     } else {
417         /* ASSERT: macro_operator == 0 */
418         *forms_count  = 0;
419         *formcode_array = 0;
420     }
421     return DW_DLV_OK;
422 }
423 
424 
425 /*  Here a DW_DLV_NO_ENTRY return means the macro operator
426     is not a def/undef operator. */
427 int
428 dwarf_get_macro_defundef(Dwarf_Macro_Context macro_context,
429     Dwarf_Unsigned op_number,
430     Dwarf_Unsigned * line_number,
431     Dwarf_Unsigned * index,
432     Dwarf_Unsigned * offset,
433     Dwarf_Half     * forms_count,
434     const char     ** macro_string,
435     Dwarf_Error *error)
436 {
437     Dwarf_Debug dbg = 0;
438     Dwarf_Small *mdata = 0;
439     int res = 0;
440     Dwarf_Small *startptr = 0;
441     Dwarf_Small *endptr = 0;
442     Dwarf_Half lformscount = 0;
443     struct Dwarf_Macro_Operator_s *curop = 0;
444     unsigned macop = 0;
445 
446     if (!macro_context || macro_context->mc_sentinel != 0xada) {
447         if(macro_context) {
448             dbg = macro_context->mc_dbg;
449         }
450         _dwarf_error(dbg, error,DW_DLE_BAD_MACRO_HEADER_POINTER);
451         return DW_DLV_ERROR;
452     }
453     dbg = macro_context->mc_dbg;
454     if (op_number >= macro_context->mc_macro_ops_count) {
455         _dwarf_error(dbg, error,DW_DLE_BAD_MACRO_INDEX);
456         return DW_DLV_ERROR;
457     }
458     curop = macro_context->mc_ops + op_number;
459     macop = curop->mo_opcode;
460     startptr = macro_context->mc_macro_header;
461     endptr = startptr + macro_context->mc_total_length;
462     mdata = curop->mo_data;
463     lformscount = curop->mo_form->mf_formcount;
464     if (lformscount != 2) {
465         /*_dwarf_error(dbg, error,DW_DLE_MACRO_OPCODE_FORM_BAD);*/
466         return DW_DLV_NO_ENTRY;
467     }
468     switch(macop){
469     case DW_MACRO_define:
470     case DW_MACRO_undef: {
471         Dwarf_Unsigned linenum = 0;
472         const char * content = 0;
473 
474         DECODE_LEB128_UWORD_CK(mdata,linenum,
475             dbg, error,endptr);
476         content = (const char *)mdata;
477         res = _dwarf_check_string_valid(dbg,
478             startptr,mdata, endptr,
479             DW_DLE_MACRO_STRING_BAD,error);
480         if(res != DW_DLV_OK) {
481             return res;
482         }
483         *line_number = linenum;
484         *index = 0;
485         *offset = 0;
486         *forms_count = lformscount;
487         *macro_string = content;
488         }
489         return DW_DLV_OK;
490     case DW_MACRO_define_strp:
491     case DW_MACRO_undef_strp: {
492         Dwarf_Unsigned linenum = 0;
493         Dwarf_Unsigned stringoffset = 0;
494         Dwarf_Small form1 =  curop->mo_form->mf_formbytes[1];
495         char * localstr = 0;
496 
497 
498         DECODE_LEB128_UWORD_CK(mdata,linenum,
499             dbg, error,endptr);
500         READ_UNALIGNED_CK(dbg,stringoffset,Dwarf_Unsigned,
501             mdata,macro_context->mc_offset_size,
502             error,endptr);
503         res = _dwarf_extract_local_debug_str_string_given_offset(dbg,
504             form1,
505             stringoffset,
506             &localstr,
507             error);
508         *index = 0;
509         *line_number = linenum;
510         *offset = stringoffset;
511         *forms_count = lformscount;
512         if (res == DW_DLV_ERROR) {
513             *macro_string = "<Error: getting local .debug_str>";
514             return res;
515         } else if (res == DW_DLV_NO_ENTRY) {
516             *macro_string = "<Error: NO_ENTRY on .debug_string (strp)>";
517         } else {
518             *macro_string = (const char *)localstr;
519         }
520         }
521         return DW_DLV_OK;
522     case DW_MACRO_define_strx:
523     case DW_MACRO_undef_strx: {
524         Dwarf_Unsigned linenum = 0;
525         Dwarf_Unsigned stringindex = 0;
526         Dwarf_Unsigned offsettostr= 0;
527         int ress = 0;
528         Dwarf_Byte_Ptr mdata_copy = 0;
529         Dwarf_Small form1 =  curop->mo_form->mf_formbytes[1];
530 
531         DECODE_LEB128_UWORD_CK(mdata,linenum, dbg, error,endptr);
532         *line_number = linenum;
533         mdata_copy = mdata;
534         DECODE_LEB128_UWORD_CK(mdata_copy,stringindex, dbg, error,endptr);
535         /* mdata_copy is for call below */
536 
537 
538         *index = stringindex;
539         *forms_count = lformscount;
540 
541         /* Redoes the index-getting. Gets offset. */
542         ress = _dwarf_extract_string_offset_via_str_offsets(dbg,
543             mdata_copy,
544             endptr,
545             DW_AT_macros, /*arbitrary, unused by called routine. */
546             form1,
547             macro_context->mc_cu_context,
548             &offsettostr,
549             error);
550         if (ress  == DW_DLV_ERROR) {
551             return ress;
552         }
553         if (ress == DW_DLV_OK) {
554             char *localstr = 0;
555 
556             *index = stringindex;
557             *offset = offsettostr;
558             ress = _dwarf_extract_local_debug_str_string_given_offset(dbg,
559                 form1,
560                 offsettostr,
561                 &localstr,
562                 error);
563             if(ress == DW_DLV_ERROR) {
564                 return ress;
565             } else if (ress == DW_DLV_NO_ENTRY){
566                 *macro_string = "<:No string available>";
567             } else {
568                 *macro_string = (const char *)localstr;
569                 /* All is ok. */
570             }
571         } else {
572             *index = stringindex;
573             *offset = 0;
574             *macro_string = "<.debug_str_offsets not available>";
575         }
576         }
577         return DW_DLV_OK;
578     case DW_MACRO_define_sup:
579     case DW_MACRO_undef_sup: {
580         Dwarf_Unsigned linenum = 0;
581         Dwarf_Unsigned supoffset = 0;
582         char *localstring = 0;
583         int resup = 0;
584         Dwarf_Error lerr = 0;
585 
586         DECODE_LEB128_UWORD_CK(mdata,linenum,
587             dbg, error,endptr);
588         READ_UNALIGNED_CK(dbg,supoffset,Dwarf_Unsigned,
589             mdata,macro_context->mc_offset_size,
590             error,endptr);
591         *line_number = linenum;
592         *index = 0;
593         *offset = supoffset;
594         *forms_count = lformscount;
595         resup = _dwarf_get_string_from_tied(dbg, supoffset,
596             &localstring, &lerr);
597         if (resup != DW_DLV_OK) {
598             if (resup == DW_DLV_ERROR) {
599                 int myerrno = dwarf_errno(lerr);
600                 if(myerrno == DW_DLE_NO_TIED_FILE_AVAILABLE) {
601                     *macro_string =
602                         (char *)"<DW_FORM_str_sup-no-tied_file>";
603                 } else {
604                     _dwarf_error(dbg,error,myerrno);
605                     *macro_string =
606                         (char *)"<Error: DW_FORM_str_sup-got-error>";
607                 }
608                 dwarf_dealloc(dbg,lerr,DW_DLA_ERROR);
609             } else {
610                 *macro_string = "<DW_FORM_str_sup-no-entry>";
611             }
612             return resup;
613         }
614         *macro_string = (const char *)localstring;
615         /*  If NO ENTRY available, return DW_DLV_NO_ENTRY.
616             We suspect this is better than DW_DLV_OK.  */
617         return resup;
618         }
619     default:
620         _dwarf_error(dbg,error,DW_DLE_MACRO_OP_UNHANDLED);
621         return DW_DLV_ERROR;
622     }
623     return DW_DLV_NO_ENTRY;
624 }
625 
626 /*  ASSERT: we elsewhere guarantee room to copy into.
627     If trimtarg ==1, trim trailing slash in targ.
628     Caller should not pass in 'src'
629     with leading /  */
630 static void
631 specialcat(char *targ,char *src,int trimtarg)
632 {
633     char *last = 0;
634 
635     while( *targ) {
636         last = targ;
637         targ++;
638     }
639     /* TARG now points at terminating NUL */
640     /* LAST points at final character in targ. */
641     if (trimtarg ) {
642         if(last && *last == '/') {
643             /* Truncate. */
644             *last = 0;
645             targ = last;
646             /* TARG again points at terminating NUL */
647         }
648     }
649     while (*src) {
650         *targ = *src;
651         targ++;
652         src++;
653     }
654     *targ = 0;
655 }
656 
657 /* If returns NULL caller must handle it. */
658 static const char *
659 construct_from_dir_and_name(const char *dir,
660    const char *name)
661 {
662     int truelen = 0;
663     char *final = 0;
664 
665     /* Allow for NUL char and added /  */
666     truelen = strlen(dir) + strlen(name) + 1 +1;
667     final = (char *)malloc(truelen);
668     if(!final) {
669         return NULL;
670     }
671     final[0] = 0;
672     specialcat(final,(char *)dir,1);
673     strcat(final,"/");
674     specialcat(final,(char *)name,0);
675     return final;
676 }
677 
678 /* If returns NULL caller must handle it. */
679 static const char *
680 construct_at_path_from_parts(Dwarf_Macro_Context mc)
681 {
682     if (mc->mc_file_path) {
683         return mc->mc_file_path;
684     }
685     if(!mc->mc_at_comp_dir || !mc->mc_at_comp_dir[0]) {
686         return mc->mc_at_name;
687     }
688     if (!mc->mc_at_name || !mc->mc_at_name[0]) {
689         return NULL;
690     }
691     if(_dwarf_file_name_is_full_path((Dwarf_Small *)mc->mc_at_name)) {
692         return mc->mc_at_name;
693     }
694     /* Dwarf_Macro_Context destructor will free this. */
695     mc->mc_file_path = construct_from_dir_and_name(
696         mc->mc_at_comp_dir,mc->mc_at_name);
697     return mc->mc_file_path;
698 }
699 
700 
701 int
702 dwarf_get_macro_startend_file(Dwarf_Macro_Context macro_context,
703     Dwarf_Unsigned op_number,
704     Dwarf_Unsigned * line_number,
705     Dwarf_Unsigned * name_index_to_line_tab,
706     const char     ** src_file_name,
707     Dwarf_Error *error)
708 {
709     Dwarf_Debug dbg = 0;
710     Dwarf_Small *mdata = 0;
711     unsigned macop = 0;
712     struct Dwarf_Macro_Operator_s *curop = 0;
713     Dwarf_Byte_Ptr startptr =  0;
714     Dwarf_Byte_Ptr endptr =  0;
715 
716     if (!macro_context || macro_context->mc_sentinel != 0xada) {
717         if(macro_context) {
718             dbg = macro_context->mc_dbg;
719         }
720         _dwarf_error(dbg, error,DW_DLE_BAD_MACRO_HEADER_POINTER);
721         return DW_DLV_ERROR;
722     }
723     dbg = macro_context->mc_dbg;
724     if (op_number >= macro_context->mc_macro_ops_count) {
725         _dwarf_error(dbg, error,DW_DLE_BAD_MACRO_INDEX);
726         return DW_DLV_ERROR;
727     }
728     startptr = macro_context->mc_macro_header;
729     endptr = startptr + macro_context->mc_total_length;
730 
731     curop = macro_context->mc_ops + op_number;
732     macop = curop->mo_opcode;
733     mdata = curop->mo_data;
734     if (macop != DW_MACRO_start_file && macop != DW_MACRO_end_file) {
735         return DW_DLV_NO_ENTRY;
736     }
737     if (macop == DW_MACRO_start_file) {
738         Dwarf_Unsigned linenum = 0;
739         Dwarf_Unsigned srcindex = 0;
740         Dwarf_Signed trueindex = 0;
741 
742         DECODE_LEB128_UWORD_CK(mdata,linenum, dbg, error,endptr);
743         DECODE_LEB128_UWORD_CK(mdata,srcindex, dbg, error,endptr);
744         *line_number = linenum;
745         *name_index_to_line_tab = srcindex;
746         /*  For DWARF 2,3,4, decrement by 1.
747             FOR DWARF 5 do not decrement. */
748         if(macro_context->mc_version_number >= 5) {
749             trueindex = srcindex;
750             if (trueindex < 0) {
751                 *src_file_name = "<source-file-index-low-no-name-available>";
752                 return DW_DLV_OK;
753             }
754             if (trueindex < macro_context->mc_srcfiles_count) {
755                 *src_file_name = macro_context->mc_srcfiles[trueindex];
756                 return DW_DLV_OK;
757             } else {
758                 *src_file_name =
759                     "<src-index-high-no-source-file-name-available>";
760                 return DW_DLV_OK;
761             }
762         } else {
763             /* Unsigned to signed here. */
764             trueindex = srcindex;
765             /* Protects against crazy big srcindex, overflow territory. */
766             if (trueindex < 0 ) {
767                 /* Something insane here. */
768                 *src_file_name = "<source-file-index-low-no-name-available>";
769                 return DW_DLV_OK;
770             }
771             /* Protects against crazy big srcindex, overflow territory. */
772             if (trueindex > (macro_context->mc_srcfiles_count+1)) {
773                 /* Something insane here. */
774                 *src_file_name =
775                     "<source-file-index-high-no-name-available>";
776                 return DW_DLV_OK;
777             }
778             --trueindex;
779             if (trueindex > macro_context->mc_srcfiles_count) {
780                 *src_file_name =
781                     "<adjusted-source-file-index-high-no-name-available>";
782             }
783             if (srcindex > 0 &&
784                 trueindex < macro_context->mc_srcfiles_count) {
785                 *src_file_name = macro_context->mc_srcfiles[trueindex];
786             } else {
787                 const char *mcatcomp = construct_at_path_from_parts(
788                     macro_context);
789                 if(mcatcomp) {
790                     *src_file_name = mcatcomp;
791                 } else {
792                     *src_file_name = "<no-source-file-name-available>";
793                 }
794             }
795         }
796     } else {
797         /* DW_MACRO_end_file. No operands. */
798     }
799     return DW_DLV_OK;
800 }
801 
802 /*  Target_offset is the offset in a .debug_macro section,
803     of a macro unit header.
804     Returns DW_DLV_NO_ENTRY if the macro operator is not
805     one of the import operators.  */
806 int
807 dwarf_get_macro_import(Dwarf_Macro_Context macro_context,
808     Dwarf_Unsigned   op_number,
809     Dwarf_Unsigned * target_offset,
810     Dwarf_Error *error)
811 {
812     Dwarf_Unsigned supoffset = 0;
813     Dwarf_Debug dbg = 0;
814     unsigned macop = 0;
815     struct Dwarf_Macro_Operator_s *curop = 0;
816     Dwarf_Small *mdata = 0;
817     Dwarf_Byte_Ptr startptr =  0;
818     Dwarf_Byte_Ptr endptr =  0;
819 
820     if (!macro_context || macro_context->mc_sentinel != 0xada) {
821         if(macro_context) {
822             dbg = macro_context->mc_dbg;
823         }
824         _dwarf_error(dbg, error,DW_DLE_BAD_MACRO_HEADER_POINTER);
825         return DW_DLV_ERROR;
826     }
827     startptr = macro_context->mc_macro_header;
828     endptr = startptr + macro_context->mc_total_length;
829     dbg = macro_context->mc_dbg;
830     if (op_number >= macro_context->mc_macro_ops_count) {
831         _dwarf_error(dbg, error,DW_DLE_BAD_MACRO_INDEX);
832         return DW_DLV_ERROR;
833     }
834     curop = macro_context->mc_ops + op_number;
835     macop = curop->mo_opcode;
836     mdata = curop->mo_data;
837     if (macop != DW_MACRO_import && macop != DW_MACRO_import_sup) {
838         return DW_DLV_NO_ENTRY;
839     }
840     READ_UNALIGNED_CK(dbg,supoffset,Dwarf_Unsigned,
841         mdata,macro_context->mc_offset_size,
842         error,endptr);
843     *target_offset = supoffset;
844     return DW_DLV_OK;
845 }
846 
847 /* */
848 static int
849 valid_macro_form(Dwarf_Half form)
850 {
851     switch(form) {
852     case DW_FORM_block:
853     case DW_FORM_block1:
854     case DW_FORM_block2:
855     case DW_FORM_block4:
856     case DW_FORM_data1:
857     case DW_FORM_data2:
858     case DW_FORM_data4:
859     case DW_FORM_data8:
860     case DW_FORM_data16:
861     case DW_FORM_sdata:
862     case DW_FORM_udata:
863     case DW_FORM_flag:
864     case DW_FORM_sec_offset:
865     case DW_FORM_string:
866     case DW_FORM_strp:
867     case DW_FORM_strx:
868         return TRUE;
869     }
870     return FALSE;
871 }
872 
873 static int
874 validate_opcode(Dwarf_Debug dbg,
875    struct Dwarf_Macro_Forms_s *curform,
876    Dwarf_Error * error)
877 {
878     unsigned i = 0;
879     struct Dwarf_Macro_Forms_s *stdfptr = 0;
880     if (curform->mf_code >= DW_MACRO_lo_user) {
881         /* Nothing to check. user level. */
882         return DW_DLV_OK;
883     }
884     if (curform->mf_code > DW_MACRO_undef_strx) {
885         _dwarf_error(dbg, error, DW_DLE_MACRO_OPCODE_BAD);
886         return (DW_DLV_ERROR);
887     }
888     if (!curform->mf_code){
889         _dwarf_error(dbg, error, DW_DLE_MACRO_OPCODE_BAD);
890         return (DW_DLV_ERROR);
891     }
892     stdfptr = &dwarf_default_macro_opslist.mol_data[curform->mf_code];
893 
894     if (curform->mf_formcount != stdfptr->mf_formcount) {
895         _dwarf_error(dbg, error, DW_DLE_MACRO_OPCODE_FORM_BAD);
896         return (DW_DLV_ERROR);
897     }
898     for(i = 0; i < curform->mf_formcount; ++i) {
899         if (curform->mf_formbytes[i] != stdfptr->mf_formbytes[1]) {
900             _dwarf_error(dbg, error, DW_DLE_MACRO_OPCODE_FORM_BAD);
901             return (DW_DLV_ERROR);
902         }
903     }
904     return DW_DLV_OK;
905 }
906 
907 static int
908 read_operands_table(Dwarf_Macro_Context macro_context,
909     Dwarf_Small * macro_header,
910     Dwarf_Small * macro_data,
911     Dwarf_Small * section_base,
912     Dwarf_Unsigned section_size,
913     Dwarf_Unsigned *table_size_out,
914     Dwarf_Error *error)
915 {
916     Dwarf_Small* table_data_start = macro_data;
917     Dwarf_Unsigned local_size = 0;
918     Dwarf_Unsigned cur_offset = 0;
919     Dwarf_Small operand_table_count = 0;
920     unsigned i = 0;
921     struct Dwarf_Macro_Forms_s *curformentry = 0;
922     Dwarf_Debug dbg = 0;
923     Dwarf_Byte_Ptr startptr = 0;
924     Dwarf_Byte_Ptr endptr = 0;
925 
926     if (!macro_context || macro_context->mc_sentinel != 0xada) {
927         if(macro_context) {
928             dbg = macro_context->mc_dbg;
929         }
930         _dwarf_error(dbg, error,DW_DLE_BAD_MACRO_HEADER_POINTER);
931         return DW_DLV_ERROR;
932     }
933 
934     dbg = macro_context->mc_dbg;
935     cur_offset = (1+ macro_data) - macro_header;
936     if (cur_offset >= section_size) {
937         _dwarf_error(dbg, error, DW_DLE_MACRO_OFFSET_BAD);
938         return (DW_DLV_ERROR);
939     }
940 
941     startptr = macro_context->mc_macro_header;
942     endptr = startptr + macro_context->mc_total_length;
943     READ_UNALIGNED_CK(dbg,operand_table_count,Dwarf_Small,
944         macro_data,sizeof(Dwarf_Small),error,endptr);
945     macro_data += sizeof(Dwarf_Small);
946     /* Estimating minimum size */
947     local_size = operand_table_count * 4;
948 
949     cur_offset = (local_size+ macro_data) - section_base;
950     if (cur_offset >= section_size) {
951         _dwarf_error(dbg, error, DW_DLE_MACRO_OFFSET_BAD);
952         return (DW_DLV_ERROR);
953     }
954     /* first, get size of table. */
955     table_data_start = macro_data;
956     for (i = 0; i < operand_table_count; ++i) {
957         /*  Compiler warning about unused opcode_number
958             variable should be ignored. */
959         UNUSEDARG Dwarf_Small opcode_number = 0;
960         Dwarf_Unsigned formcount = 0;
961         READ_UNALIGNED_CK(dbg,opcode_number,Dwarf_Small,
962             macro_data,sizeof(Dwarf_Small),error,endptr);
963         macro_data += sizeof(Dwarf_Small);
964 
965         DECODE_LEB128_UWORD_CK(macro_data,formcount,
966             dbg, error, endptr);
967         cur_offset = (formcount+ macro_data) - section_base;
968         if (cur_offset >= section_size) {
969             _dwarf_error(dbg, error, DW_DLE_MACRO_OFFSET_BAD);
970             return (DW_DLV_ERROR);
971         }
972         /* The 1 ubyte forms follow. Step past them. */
973         macro_data += formcount;
974     }
975     /* reset for reread. */
976     macro_data = table_data_start;
977     /* allocate table */
978     macro_context->mc_opcode_forms =  (struct Dwarf_Macro_Forms_s *)
979         calloc(operand_table_count,
980             sizeof(struct Dwarf_Macro_Forms_s));
981     macro_context->mc_opcode_count = operand_table_count;
982     if(!macro_context->mc_opcode_forms) {
983         _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
984         return DW_DLV_ERROR;
985     }
986 
987     curformentry = macro_context->mc_opcode_forms;
988     for (i = 0; i < operand_table_count; ++i,++curformentry) {
989         Dwarf_Small opcode_number = 0;
990         Dwarf_Unsigned formcount = 0;
991         int res = 0;
992 
993         cur_offset = (2 + macro_data) - section_base;
994         if (cur_offset >= section_size) {
995             _dwarf_error(dbg, error, DW_DLE_MACRO_OFFSET_BAD);
996             return (DW_DLV_ERROR);
997         }
998         READ_UNALIGNED_CK(dbg,opcode_number,Dwarf_Small,
999             macro_data,sizeof(Dwarf_Small),
1000             error,endptr);
1001         macro_data += sizeof(Dwarf_Small);
1002         DECODE_LEB128_UWORD_CK(macro_data,formcount,
1003             dbg, error, endptr);
1004 
1005         curformentry->mf_code = opcode_number;
1006         curformentry->mf_formcount = formcount;
1007 
1008         cur_offset = (formcount+ macro_data) - section_base;
1009         if (cur_offset >= section_size) {
1010             _dwarf_error(dbg, error, DW_DLE_MACRO_OFFSET_BAD);
1011             return (DW_DLV_ERROR);
1012         }
1013         curformentry->mf_formbytes = macro_data;
1014         macro_data += formcount;
1015         if (opcode_number  > DW_MACRO_undef_strx ) {
1016             Dwarf_Half k = 0;
1017             for(k = 0; k < formcount; ++k) {
1018                 if (!valid_macro_form(curformentry->mf_formbytes[k])) {
1019                     _dwarf_error(dbg, error, DW_DLE_MACRO_OP_UNHANDLED);
1020                     return (DW_DLV_ERROR);
1021                 }
1022             }
1023         }
1024         res = validate_opcode(macro_context->mc_dbg,curformentry, error);
1025         if(res != DW_DLV_OK) {
1026             return res;
1027         }
1028     }
1029     *table_size_out = macro_data - table_data_start;
1030     return DW_DLV_OK;
1031 }
1032 
1033 /*  This is not the normal srcfiles from dwarf_srcfiles.
1034     See translate translate_srcfiles_to_srcfiles2().
1035     It is a list, but the contents were directly malloc,
1036     not _dwarf_get_alloc.
1037 */
1038 static void
1039 dealloc_macro_srcfiles(char ** srcfiles,
1040     Dwarf_Signed srcfiles_count)
1041 {
1042     Dwarf_Signed i = 0;
1043     if (!srcfiles || !srcfiles_count) {
1044         return;
1045     }
1046     for (i = 0; i < srcfiles_count; ++i) {
1047         if (srcfiles[i]) {
1048             free(srcfiles[i]);
1049             srcfiles[i] = 0;
1050         }
1051     }
1052     free(srcfiles);
1053 }
1054 
1055 /*  This makes the macro context safe from
1056     duplicate frees in case of error. */
1057 static int
1058 translate_srcfiles_to_srcfiles2(char **srcfiles,
1059    Dwarf_Signed srcfiles_count,
1060    char **srcfiles2)
1061 {
1062     Dwarf_Signed i = 0;
1063 
1064     for(i = 0; i < srcfiles_count; ++i) {
1065         char * ostr = 0;
1066         char * newstr = 0;
1067         size_t slen = 0;
1068 
1069         ostr = srcfiles[i];
1070         slen = strlen(ostr);
1071         newstr =  calloc(1,slen+1);
1072         if (!newstr) {
1073             return DW_DLV_ERROR;
1074         }
1075         strcpy(newstr,ostr);
1076         srcfiles2[i] = newstr;
1077     }
1078     return DW_DLV_OK;
1079 }
1080 
1081 static void
1082 drop_srcfiles(Dwarf_Debug dbg,char ** srcfiles,
1083     Dwarf_Signed srcfiles_count)
1084 {
1085     Dwarf_Signed i = 0;
1086     for (i = 0; i < srcfiles_count; ++i) {
1087         if(srcfiles[i]) {
1088             dwarf_dealloc(dbg, srcfiles[i], DW_DLA_STRING);
1089         }
1090     }
1091     dwarf_dealloc(dbg, srcfiles, DW_DLA_LIST);
1092 }
1093 
1094 
1095 static int
1096 _dwarf_internal_macro_context(Dwarf_Die die,
1097     Dwarf_Bool        offset_specified,
1098     Dwarf_Unsigned    offset_in,
1099     Dwarf_Unsigned  * version_out,
1100     Dwarf_Macro_Context * macro_context_out,
1101     Dwarf_Unsigned      * macro_unit_offset_out,
1102     Dwarf_Unsigned      * macro_ops_count_out,
1103     Dwarf_Unsigned      * macro_ops_data_length,
1104     Dwarf_Error * error)
1105 {
1106     Dwarf_CU_Context   cu_context = 0;
1107 
1108     /*  The Dwarf_Debug this die belongs to. */
1109     Dwarf_Debug dbg = 0;
1110     int resattr = DW_DLV_ERROR;
1111     int lres = DW_DLV_ERROR;
1112     int res = DW_DLV_ERROR;
1113     Dwarf_Unsigned macro_offset = 0;
1114     Dwarf_Attribute macro_attr = 0;
1115     Dwarf_Signed srcfiles_count = 0;
1116     Dwarf_Signed srcfiles2_count = 0;
1117     char ** srcfiles = 0;
1118 
1119     /*  srcfiles uses dwarf_get_alloc for strings
1120         so dealloc_macro_srcfiles() here will result in double-dealloc
1121         when dwarf_finish() happens to see the string deallocs
1122         before the macro context dealloc (the context dealloc
1123         will call dealloc_macro_srcfiles() !).
1124 
1125         Also see the comment at _dwarf_macro_destructor() here.
1126     */
1127     char ** srcfiles2 = 0;
1128 
1129     const char *comp_dir = 0;
1130     const char *comp_name = 0;
1131 
1132     /*  ***** BEGIN CODE ***** */
1133     if (error != NULL) {
1134         *error = NULL;
1135     }
1136 
1137     CHECK_DIE(die, DW_DLV_ERROR);
1138     cu_context = die->di_cu_context;
1139     dbg = cu_context->cc_dbg;
1140 
1141     /*  Doing the load here results in duplication of the
1142         section-load call  (in the by_offset
1143         interface below) but detects the missing section
1144         quickly. */
1145     res = _dwarf_load_section(dbg, &dbg->de_debug_macro,error);
1146     if (res != DW_DLV_OK) {
1147         return res;
1148     }
1149     if (!dbg->de_debug_macro.dss_size) {
1150         return (DW_DLV_NO_ENTRY);
1151     }
1152     resattr = dwarf_attr(die, DW_AT_macros, &macro_attr, error);
1153     if (resattr == DW_DLV_NO_ENTRY) {
1154         resattr = dwarf_attr(die, DW_AT_GNU_macros, &macro_attr, error);
1155     }
1156     if (resattr != DW_DLV_OK) {
1157         return resattr;
1158     }
1159     if (!offset_specified) {
1160         lres = dwarf_global_formref(macro_attr, &macro_offset, error);
1161         if (lres != DW_DLV_OK) {
1162             dwarf_dealloc(dbg,macro_attr,DW_DLA_ATTR);
1163             return lres;
1164         }
1165     } else {
1166         macro_offset = offset_in;
1167     }
1168     lres = dwarf_srcfiles(die,&srcfiles,&srcfiles_count, error);
1169     if (lres == DW_DLV_ERROR) {
1170         dwarf_dealloc(dbg,macro_attr,DW_DLA_ATTR);
1171         return lres;
1172     }
1173     lres = _dwarf_internal_get_die_comp_dir(die, &comp_dir,
1174         &comp_name,error);
1175     if (lres == DW_DLV_ERROR) {
1176         drop_srcfiles(dbg,srcfiles,srcfiles_count);
1177         srcfiles = 0;
1178         srcfiles_count = 0;
1179         dwarf_dealloc(dbg,macro_attr,DW_DLA_ATTR);
1180         srcfiles = 0;
1181         return lres;
1182     }
1183     *macro_unit_offset_out = macro_offset;
1184     /*  We cannot use space allocated by
1185         _dwarf_get_alloc() in the macro_context
1186         we will allocate shortly.
1187         So copy from what we have to a similar data set
1188         but malloc space directly. */
1189 
1190     if (srcfiles_count > 0) {
1191         srcfiles2 = (char **) calloc(srcfiles_count, sizeof(char *));
1192         if (!srcfiles2) {
1193             dwarf_dealloc(dbg,macro_attr,DW_DLA_ATTR);
1194             drop_srcfiles(dbg,srcfiles,srcfiles_count);
1195             _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
1196             return (DW_DLV_ERROR);
1197         }
1198         lres  = translate_srcfiles_to_srcfiles2(srcfiles,
1199             srcfiles_count,srcfiles2);
1200         drop_srcfiles(dbg,srcfiles,srcfiles_count);
1201         srcfiles2_count = srcfiles_count;
1202         srcfiles = 0;
1203         srcfiles_count = 0;
1204         if (lres != DW_DLV_OK) {
1205             dwarf_dealloc(dbg,macro_attr,DW_DLA_ATTR);
1206             dealloc_macro_srcfiles(srcfiles2, srcfiles2_count);
1207             _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
1208             return lres;
1209         }
1210     } else {
1211         drop_srcfiles(dbg,srcfiles,srcfiles_count);
1212         srcfiles = 0;
1213         srcfiles_count = 0;
1214     }
1215 
1216     dwarf_dealloc(dbg,macro_attr,DW_DLA_ATTR);
1217     /*  NO ENTRY or OK we accept, though NO ENTRY means there
1218         are no source files available. */
1219     lres = _dwarf_internal_macro_context_by_offset(dbg,
1220         macro_offset,version_out,macro_context_out,
1221         macro_ops_count_out,
1222         macro_ops_data_length,
1223         srcfiles2,srcfiles2_count,
1224         comp_dir,
1225         comp_name,
1226         cu_context,
1227         error);
1228     /*  In case of ERROR or NO_ENTRY srcfiles2 is already freed. */
1229     return lres;
1230 }
1231 
1232 static int
1233 _dwarf_internal_macro_context_by_offset(Dwarf_Debug dbg,
1234     Dwarf_Unsigned offset,
1235     Dwarf_Unsigned  * version_out,
1236     Dwarf_Macro_Context * macro_context_out,
1237     Dwarf_Unsigned      * macro_ops_count_out,
1238     Dwarf_Unsigned      * macro_ops_data_length,
1239     char **srcfiles,
1240     Dwarf_Signed srcfilescount,
1241     const char *comp_dir,
1242     const char *comp_name,
1243     Dwarf_CU_Context cu_context,
1244     Dwarf_Error * error)
1245 {
1246     Dwarf_Unsigned line_table_offset = 0;
1247     Dwarf_Small * macro_header = 0;
1248     Dwarf_Small * macro_data = 0;
1249     Dwarf_Unsigned version = 0;
1250     Dwarf_Unsigned flags = 0;
1251     Dwarf_Small offset_size = 4;
1252     Dwarf_Unsigned cur_offset = 0;
1253     Dwarf_Unsigned section_size = 0;
1254     Dwarf_Small *section_base = 0;
1255     Dwarf_Small *section_end = 0;
1256     Dwarf_Unsigned optablesize = 0;
1257     Dwarf_Unsigned macro_offset = offset;
1258     int res = 0;
1259     Dwarf_Macro_Context macro_context = 0;
1260     Dwarf_Bool build_ops_array = FALSE;
1261 
1262     res = _dwarf_load_section(dbg, &dbg->de_debug_macro,error);
1263     if (res != DW_DLV_OK) {
1264         dealloc_macro_srcfiles(srcfiles,srcfilescount);
1265         return res;
1266     }
1267     if (!dbg->de_debug_macro.dss_size) {
1268         dealloc_macro_srcfiles(srcfiles,srcfilescount);
1269         return (DW_DLV_NO_ENTRY);
1270     }
1271 
1272     section_base = dbg->de_debug_macro.dss_data;
1273     section_size = dbg->de_debug_macro.dss_size;
1274     /*  The '3'  ensures the header initial bytes present too. */
1275     if ((3+macro_offset) >= section_size) {
1276         dealloc_macro_srcfiles(srcfiles,srcfilescount);
1277         _dwarf_error(dbg, error, DW_DLE_MACRO_OFFSET_BAD);
1278         return (DW_DLV_ERROR);
1279     }
1280     macro_header = macro_offset + section_base;
1281     macro_data = macro_header;
1282     section_end = section_base +section_size;
1283 
1284 
1285     macro_context = (Dwarf_Macro_Context)
1286         _dwarf_get_alloc(dbg,DW_DLA_MACRO_CONTEXT,1);
1287     if (!macro_context) {
1288         dealloc_macro_srcfiles(srcfiles,srcfilescount);
1289         _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
1290         return DW_DLV_ERROR;
1291     }
1292 
1293     if ((section_base + DWARF_HALF_SIZE + sizeof(Dwarf_Small)) >                     section_end ) {
1294         dealloc_macro_srcfiles(srcfiles,srcfilescount);
1295         dwarf_dealloc_macro_context(macro_context);
1296         _dwarf_error(dbg, error, DW_DLE_MACRO_OFFSET_BAD);
1297         return DW_DLV_ERROR;
1298     }
1299     /* Note here so if error return we get these freed eventually. */
1300     macro_context->mc_srcfiles = srcfiles;
1301     macro_context->mc_srcfiles_count = srcfilescount;
1302     macro_context->mc_cu_context =  cu_context;
1303 
1304     res = _dwarf_read_unaligned_ck_wrapper(dbg,
1305         &version,macro_data,DWARF_HALF_SIZE,section_end,
1306         error);
1307     if (res != DW_DLV_OK) {
1308         dwarf_dealloc_macro_context(macro_context);
1309         return res;
1310     }
1311     macro_data +=  DWARF_HALF_SIZE;
1312     res = _dwarf_read_unaligned_ck_wrapper(dbg,
1313         &flags,macro_data,sizeof(Dwarf_Small),section_end,
1314         error);
1315     if (res != DW_DLV_OK) {
1316         dwarf_dealloc_macro_context(macro_context);
1317         return res;
1318     }
1319     macro_data += sizeof(Dwarf_Small);
1320 
1321     macro_context->mc_at_comp_dir = comp_dir;
1322     macro_context->mc_at_name = comp_name;
1323     macro_context->mc_macro_header = macro_header;
1324     macro_context->mc_section_offset = macro_offset;
1325     macro_context->mc_version_number = version;
1326     macro_context->mc_flags = flags;
1327     macro_context->mc_dbg = dbg;
1328     macro_context->mc_offset_size_flag =
1329         flags& MACRO_OFFSET_SIZE_FLAG?TRUE:FALSE;
1330     macro_context->mc_debug_line_offset_flag =
1331         flags& MACRO_LINE_OFFSET_FLAG?TRUE:FALSE;
1332     macro_context->mc_operands_table_flag =
1333         flags& MACRO_OP_TABLE_FLAG?TRUE:FALSE;
1334     offset_size = macro_context->mc_offset_size_flag?8:4;
1335     macro_context->mc_offset_size = offset_size;
1336     if (macro_context->mc_debug_line_offset_flag) {
1337         cur_offset = (offset_size+ macro_data) - section_base;
1338         if (cur_offset >= section_size) {
1339             dwarf_dealloc_macro_context(macro_context);
1340             _dwarf_error(dbg, error, DW_DLE_MACRO_OFFSET_BAD);
1341             return (DW_DLV_ERROR);
1342         }
1343         res = _dwarf_read_unaligned_ck_wrapper(dbg,
1344             &line_table_offset,macro_data,
1345             offset_size,section_end,
1346             error);
1347         if (res != DW_DLV_OK) {
1348             dwarf_dealloc_macro_context(macro_context);
1349             return res;
1350         }
1351         macro_data += offset_size;
1352         macro_context->mc_debug_line_offset = line_table_offset;
1353     }
1354     if (macro_context->mc_operands_table_flag) {
1355         res = read_operands_table(macro_context,
1356             macro_header,
1357             macro_data,
1358             section_base,
1359             section_size,
1360             &optablesize,
1361             error);
1362         if (res != DW_DLV_OK) {
1363             dwarf_dealloc_macro_context(macro_context);
1364             return res;
1365         }
1366     }
1367 
1368     macro_data += optablesize;
1369     macro_context->mc_macro_ops = macro_data;
1370     macro_context->mc_macro_header_length =macro_data - macro_header;
1371 
1372     build_ops_array = FALSE;
1373     res = _dwarf_get_macro_ops_count_internal(macro_context,
1374         build_ops_array,
1375         error);
1376     if (res != DW_DLV_OK) {
1377         dwarf_dealloc_macro_context(macro_context);
1378         return res;
1379     }
1380     build_ops_array = TRUE;
1381     res = _dwarf_get_macro_ops_count_internal(macro_context,
1382         build_ops_array,
1383         error);
1384     if (res != DW_DLV_OK) {
1385         dwarf_dealloc_macro_context(macro_context);
1386         return res;
1387     }
1388     *macro_ops_count_out = macro_context->mc_macro_ops_count;
1389     *macro_ops_data_length = macro_context->mc_ops_data_length;
1390     *version_out = version;
1391     *macro_context_out = macro_context;
1392     return DW_DLV_OK;
1393 }
1394 
1395 int dwarf_macro_context_head(Dwarf_Macro_Context head,
1396     Dwarf_Half     * version,
1397     Dwarf_Unsigned * mac_offset,
1398     Dwarf_Unsigned * mac_len,
1399     Dwarf_Unsigned * mac_header_len,
1400     unsigned *       flags,
1401     Dwarf_Bool *     has_line_offset,
1402     Dwarf_Unsigned * line_offset,
1403     Dwarf_Bool *     has_offset_size_64,
1404     Dwarf_Bool *     has_operands_table,
1405     Dwarf_Half *     opcode_count,
1406     Dwarf_Error *error)
1407 {
1408     if (!head || head->mc_sentinel != 0xada) {
1409         Dwarf_Debug dbg = 0;
1410         if(head) {
1411             dbg = head->mc_dbg;
1412         }
1413         _dwarf_error(dbg, error,DW_DLE_BAD_MACRO_HEADER_POINTER);
1414         return DW_DLV_ERROR;
1415     }
1416     *version = head->mc_version_number;
1417     *mac_offset = head->mc_section_offset;
1418     *mac_len    = head->mc_total_length;
1419     *mac_header_len = head->mc_macro_header_length;
1420     *flags = head->mc_flags;
1421     *line_offset = head->mc_debug_line_offset;
1422     *has_line_offset = head->mc_debug_line_offset_flag;
1423     *has_offset_size_64 = head->mc_offset_size_flag;
1424     *has_operands_table = head->mc_operands_table_flag;
1425     *opcode_count = head->mc_opcode_count;
1426     return DW_DLV_OK;
1427 }
1428 int dwarf_macro_operands_table(Dwarf_Macro_Context head,
1429     Dwarf_Half  index, /* 0 to opcode_count -1 */
1430     Dwarf_Half  *opcode_number,
1431     Dwarf_Half  *operand_count,
1432     const Dwarf_Small **operand_array,
1433     Dwarf_Error *error)
1434 {
1435     struct Dwarf_Macro_Forms_s * ops = 0;
1436     Dwarf_Debug dbg = 0;
1437     if (!head || head->mc_sentinel != 0xada) {
1438         if(head) {
1439             dbg = head->mc_dbg;
1440         }
1441         _dwarf_error(dbg, error,DW_DLE_BAD_MACRO_HEADER_POINTER);
1442         return DW_DLV_ERROR;
1443     }
1444     dbg = head->mc_dbg;
1445     if (index >= head->mc_opcode_count) {
1446         _dwarf_error(dbg, error, DW_DLE_BAD_MACRO_INDEX);
1447         return DW_DLV_ERROR;
1448     }
1449     ops = head->mc_opcode_forms + index;
1450     *opcode_number = ops->mf_code;
1451     *operand_count = ops->mf_formcount;
1452     *operand_array = ops->mf_formbytes;
1453     return DW_DLV_OK;
1454 }
1455 
1456 /*  The base interface to the .debug_macro section data
1457     for a specific CU.
1458 
1459     The version number passed back by *version_out
1460     may be 4 (a gnu extension of DWARF)  or 5. */
1461 int
1462 dwarf_get_macro_context(Dwarf_Die cu_die,
1463     Dwarf_Unsigned      * version_out,
1464     Dwarf_Macro_Context * macro_context,
1465     Dwarf_Unsigned      * macro_unit_offset_out,
1466     Dwarf_Unsigned      * macro_ops_count_out,
1467     Dwarf_Unsigned      * macro_ops_data_length,
1468     Dwarf_Error * error)
1469 {
1470     int res = 0;
1471     Dwarf_Bool offset_specified = FALSE;
1472     Dwarf_Unsigned offset = 0;
1473 
1474     res =  _dwarf_internal_macro_context(cu_die,
1475         offset_specified,
1476         offset,
1477         version_out,
1478         macro_context,
1479         macro_unit_offset_out,
1480         macro_ops_count_out,
1481         macro_ops_data_length,
1482         error);
1483     return res;
1484 }
1485 
1486 /*  Like  dwarf_get_macro_context but
1487     here we use a specfied offset  instead  of
1488     the offset in the cu_die. */
1489 int
1490 dwarf_get_macro_context_by_offset(Dwarf_Die cu_die,
1491     Dwarf_Unsigned offset,
1492     Dwarf_Unsigned      * version_out,
1493     Dwarf_Macro_Context * macro_context,
1494     Dwarf_Unsigned      * macro_ops_count_out,
1495     Dwarf_Unsigned      * macro_ops_data_length,
1496     Dwarf_Error * error)
1497 {
1498     int res = 0;
1499     Dwarf_Bool offset_specified = TRUE;
1500     Dwarf_Unsigned macro_unit_offset_out = 0;
1501 
1502     res = _dwarf_internal_macro_context(cu_die,
1503         offset_specified,
1504         offset,
1505         version_out,
1506         macro_context,
1507         &macro_unit_offset_out,
1508         macro_ops_count_out,
1509         macro_ops_data_length,
1510         error);
1511     return res;
1512 }
1513 
1514 int dwarf_get_macro_section_name(Dwarf_Debug dbg,
1515    const char **sec_name_out,
1516    UNUSEDARG Dwarf_Error *error)
1517 {
1518     struct Dwarf_Section_s *sec = 0;
1519 
1520     sec = &dbg->de_debug_macro;
1521     if (sec->dss_size == 0) {
1522         /* We don't have such a  section at all. */
1523         return DW_DLV_NO_ENTRY;
1524     }
1525     *sec_name_out = sec->dss_name;
1526     return DW_DLV_OK;
1527 }
1528 
1529 void
1530 dwarf_dealloc_macro_context(Dwarf_Macro_Context mc)
1531 {
1532     Dwarf_Debug dbg = 0;
1533 
1534     if (!mc) {
1535         return;
1536     }
1537     dbg = mc->mc_dbg;
1538     /* See _dwarf_macro_destructor() here */
1539     dwarf_dealloc(dbg,mc,DW_DLA_MACRO_CONTEXT);
1540 }
1541 
1542 int
1543 _dwarf_macro_constructor(Dwarf_Debug dbg, void *m)
1544 {
1545     /* Nothing to do, the space is zeroed out */
1546     Dwarf_Macro_Context mc= (Dwarf_Macro_Context)m;
1547     /* Arbitrary sentinel. For debugging. */
1548     mc->mc_sentinel = 0xada;
1549     mc->mc_dbg = dbg;
1550     return DW_DLV_OK;
1551 }
1552 
1553 /*  Here we free various fields of Dwarf_Macro_Context.
1554     The fields do not get dealloc'd.
1555     If we had a separate destructor for hand-calling
1556     (meaning when an error is detected during creation
1557     of a  Dwarf_Macro_Context)
1558     and one for calling by dwarf_dealloc() then
1559     we could have the hand-calling dwarf_dealloc the fields
1560     and the one called on the dealloc of a  Dwarf_Macro_Context
1561     could leave the _dwarf_get_alloc() fields for for
1562     normal dwarf_finish() cleanup.
1563 
1564     But for now we share this destructor for both purposes
1565     so no fields are _dwarf_get_alloc() and all are free-d
1566     here..
1567 */
1568 void
1569 _dwarf_macro_destructor(void *m)
1570 {
1571     Dwarf_Macro_Context mc= (Dwarf_Macro_Context)m;
1572 
1573     dealloc_macro_srcfiles(mc->mc_srcfiles, mc->mc_srcfiles_count);
1574     mc->mc_srcfiles = 0;
1575     mc->mc_srcfiles_count = 0;
1576     free((void *)mc->mc_file_path);
1577     mc->mc_file_path = 0;
1578     free(mc->mc_ops);
1579     mc->mc_ops = 0;
1580     free(mc->mc_opcode_forms);
1581     mc->mc_opcode_forms = 0;
1582     memset(mc,0,sizeof(*mc));
1583     /* Just a recognizable sentinel. For debugging.  No real meaning. */
1584     mc->mc_sentinel = 0xdeadbeef;
1585 }
1586