]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/elftoolchain/libdwarf/libdwarf_lineno.c
Import DTS from Linux 4.20
[FreeBSD/FreeBSD.git] / contrib / elftoolchain / libdwarf / libdwarf_lineno.c
1 /*-
2  * Copyright (c) 2009,2010 Kai Wang
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26
27 #include "_libdwarf.h"
28
29 ELFTC_VCSID("$Id: libdwarf_lineno.c 3164 2015-02-19 01:20:12Z kaiwang27 $");
30
31 static int
32 _dwarf_lineno_add_file(Dwarf_LineInfo li, uint8_t **p, const char *compdir,
33     Dwarf_Error *error, Dwarf_Debug dbg)
34 {
35         Dwarf_LineFile lf;
36         const char *dirname;
37         uint8_t *src;
38         int slen;
39
40         src = *p;
41
42         if ((lf = malloc(sizeof(struct _Dwarf_LineFile))) == NULL) {
43                 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
44                 return (DW_DLE_MEMORY);
45         }
46
47         lf->lf_fullpath = NULL;
48         lf->lf_fname = (char *) src;
49         src += strlen(lf->lf_fname) + 1;
50         lf->lf_dirndx = _dwarf_decode_uleb128(&src);
51         if (lf->lf_dirndx > li->li_inclen) {
52                 free(lf);
53                 DWARF_SET_ERROR(dbg, error, DW_DLE_DIR_INDEX_BAD);
54                 return (DW_DLE_DIR_INDEX_BAD);
55         }
56
57         /* Make full pathname if need. */
58         if (*lf->lf_fname != '/') {
59                 dirname = compdir;
60                 if (lf->lf_dirndx > 0)
61                         dirname = li->li_incdirs[lf->lf_dirndx - 1];
62                 if (dirname != NULL) {
63                         slen = strlen(dirname) + strlen(lf->lf_fname) + 2;
64                         if ((lf->lf_fullpath = malloc(slen)) == NULL) {
65                                 free(lf);
66                                 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
67                                 return (DW_DLE_MEMORY);
68                         }
69                         snprintf(lf->lf_fullpath, slen, "%s/%s", dirname,
70                             lf->lf_fname);
71                 }
72         }
73
74         lf->lf_mtime = _dwarf_decode_uleb128(&src);
75         lf->lf_size = _dwarf_decode_uleb128(&src);
76         STAILQ_INSERT_TAIL(&li->li_lflist, lf, lf_next);
77         li->li_lflen++;
78
79         *p = src;
80
81         return (DW_DLE_NONE);
82 }
83
84 static int
85 _dwarf_lineno_run_program(Dwarf_CU cu, Dwarf_LineInfo li, uint8_t *p,
86     uint8_t *pe, const char *compdir, Dwarf_Error *error)
87 {
88         Dwarf_Debug dbg;
89         Dwarf_Line ln, tln;
90         uint64_t address, file, line, column, opsize;
91         int is_stmt, basic_block, end_sequence;
92         int ret;
93
94 #define RESET_REGISTERS                                         \
95         do {                                                    \
96                 address        = 0;                             \
97                 file           = 1;                             \
98                 line           = 1;                             \
99                 column         = 0;                             \
100                 is_stmt        = li->li_defstmt;                \
101                 basic_block    = 0;                             \
102                 end_sequence   = 0;                             \
103         } while(0)
104
105 #define APPEND_ROW                                              \
106         do {                                                    \
107                 ln = malloc(sizeof(struct _Dwarf_Line));        \
108                 if (ln == NULL) {                               \
109                         ret = DW_DLE_MEMORY;                    \
110                         DWARF_SET_ERROR(dbg, error, ret);       \
111                         goto prog_fail;                         \
112                 }                                               \
113                 ln->ln_li     = li;                             \
114                 ln->ln_addr   = address;                        \
115                 ln->ln_symndx = 0;                              \
116                 ln->ln_fileno = file;                           \
117                 ln->ln_lineno = line;                           \
118                 ln->ln_column = column;                         \
119                 ln->ln_bblock = basic_block;                    \
120                 ln->ln_stmt   = is_stmt;                        \
121                 ln->ln_endseq = end_sequence;                   \
122                 STAILQ_INSERT_TAIL(&li->li_lnlist, ln, ln_next);\
123                 li->li_lnlen++;                                 \
124         } while(0)
125
126 #define LINE(x) (li->li_lbase + (((x) - li->li_opbase) % li->li_lrange))
127 #define ADDRESS(x) ((((x) - li->li_opbase) / li->li_lrange) * li->li_minlen)
128
129         dbg = cu->cu_dbg;
130
131         /*
132          * Set registers to their default values.
133          */
134         RESET_REGISTERS;
135
136         /*
137          * Start line number program.
138          */
139         while (p < pe) {
140                 if (*p == 0) {
141
142                         /*
143                          * Extended Opcodes.
144                          */
145
146                         p++;
147                         opsize = _dwarf_decode_uleb128(&p);
148                         switch (*p) {
149                         case DW_LNE_end_sequence:
150                                 p++;
151                                 end_sequence = 1;
152                                 APPEND_ROW;
153                                 RESET_REGISTERS;
154                                 break;
155                         case DW_LNE_set_address:
156                                 p++;
157                                 address = dbg->decode(&p, cu->cu_pointer_size);
158                                 break;
159                         case DW_LNE_define_file:
160                                 p++;
161                                 ret = _dwarf_lineno_add_file(li, &p, compdir,
162                                     error, dbg);
163                                 if (ret != DW_DLE_NONE)
164                                         goto prog_fail;
165                                 break;
166                         default:
167                                 /* Unrecognized extened opcodes. */
168                                 p += opsize;
169                         }
170
171                 } else if (*p > 0 && *p < li->li_opbase) {
172
173                         /*
174                          * Standard Opcodes.
175                          */
176
177                         switch (*p++) {
178                         case DW_LNS_copy:
179                                 APPEND_ROW;
180                                 basic_block = 0;
181                                 break;
182                         case DW_LNS_advance_pc:
183                                 address += _dwarf_decode_uleb128(&p) *
184                                     li->li_minlen;
185                                 break;
186                         case DW_LNS_advance_line:
187                                 line += _dwarf_decode_sleb128(&p);
188                                 break;
189                         case DW_LNS_set_file:
190                                 file = _dwarf_decode_uleb128(&p);
191                                 break;
192                         case DW_LNS_set_column:
193                                 column = _dwarf_decode_uleb128(&p);
194                                 break;
195                         case DW_LNS_negate_stmt:
196                                 is_stmt = !is_stmt;
197                                 break;
198                         case DW_LNS_set_basic_block:
199                                 basic_block = 1;
200                                 break;
201                         case DW_LNS_const_add_pc:
202                                 address += ADDRESS(255);
203                                 break;
204                         case DW_LNS_fixed_advance_pc:
205                                 address += dbg->decode(&p, 2);
206                                 break;
207                         case DW_LNS_set_prologue_end:
208                                 break;
209                         case DW_LNS_set_epilogue_begin:
210                                 break;
211                         case DW_LNS_set_isa:
212                                 (void) _dwarf_decode_uleb128(&p);
213                                 break;
214                         default:
215                                 /* Unrecognized extened opcodes. What to do? */
216                                 break;
217                         }
218
219                 } else {
220
221                         /*
222                          * Special Opcodes.
223                          */
224
225                         line += LINE(*p);
226                         address += ADDRESS(*p);
227                         APPEND_ROW;
228                         basic_block = 0;
229                         p++;
230                 }
231         }
232
233         return (DW_DLE_NONE);
234
235 prog_fail:
236
237         STAILQ_FOREACH_SAFE(ln, &li->li_lnlist, ln_next, tln) {
238                 STAILQ_REMOVE(&li->li_lnlist, ln, _Dwarf_Line, ln_next);
239                 free(ln);
240         }
241
242         return (ret);
243
244 #undef  RESET_REGISTERS
245 #undef  APPEND_ROW
246 #undef  LINE
247 #undef  ADDRESS
248 }
249
250 int
251 _dwarf_lineno_init(Dwarf_Die die, uint64_t offset, Dwarf_Error *error)
252 {
253         Dwarf_Debug dbg;
254         Dwarf_Section *ds;
255         Dwarf_CU cu;
256         Dwarf_Attribute at;
257         Dwarf_LineInfo li;
258         Dwarf_LineFile lf, tlf;
259         const char *compdir;
260         uint64_t length, hdroff, endoff;
261         uint8_t *p;
262         int dwarf_size, i, ret;
263
264         cu = die->die_cu;
265         assert(cu != NULL);
266
267         dbg = cu->cu_dbg;
268         assert(dbg != NULL);
269
270         if ((ds = _dwarf_find_section(dbg, ".debug_line")) == NULL)
271                 return (DW_DLE_NONE);
272
273         /*
274          * Try to find out the dir where the CU was compiled. Later we
275          * will use the dir to create full pathnames, if need.
276          */
277         compdir = NULL;
278         at = _dwarf_attr_find(die, DW_AT_comp_dir);
279         if (at != NULL) {
280                 switch (at->at_form) {
281                 case DW_FORM_strp:
282                         compdir = at->u[1].s;
283                         break;
284                 case DW_FORM_string:
285                         compdir = at->u[0].s;
286                         break;
287                 default:
288                         break;
289                 }
290         }
291
292         length = dbg->read(ds->ds_data, &offset, 4);
293         if (length == 0xffffffff) {
294                 dwarf_size = 8;
295                 length = dbg->read(ds->ds_data, &offset, 8);
296         } else
297                 dwarf_size = 4;
298
299         if (length > ds->ds_size - offset) {
300                 DWARF_SET_ERROR(dbg, error, DW_DLE_DEBUG_LINE_LENGTH_BAD);
301                 return (DW_DLE_DEBUG_LINE_LENGTH_BAD);
302         }
303
304         if ((li = calloc(1, sizeof(struct _Dwarf_LineInfo))) == NULL) {
305                 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
306                 return (DW_DLE_MEMORY);
307         }
308
309         /*
310          * Read in line number program header.
311          */
312         li->li_length = length;
313         endoff = offset + length;
314         li->li_version = dbg->read(ds->ds_data, &offset, 2); /* FIXME: verify version */
315         li->li_hdrlen = dbg->read(ds->ds_data, &offset, dwarf_size);
316         hdroff = offset;
317         li->li_minlen = dbg->read(ds->ds_data, &offset, 1);
318         if (li->li_version == 4)
319                 li->li_maxop = dbg->read(ds->ds_data, &offset, 1);
320         li->li_defstmt = dbg->read(ds->ds_data, &offset, 1);
321         li->li_lbase = dbg->read(ds->ds_data, &offset, 1);
322         li->li_lrange = dbg->read(ds->ds_data, &offset, 1);
323         li->li_opbase = dbg->read(ds->ds_data, &offset, 1);
324         STAILQ_INIT(&li->li_lflist);
325         STAILQ_INIT(&li->li_lnlist);
326
327         if ((int)li->li_hdrlen - 5 < li->li_opbase - 1) {
328                 ret = DW_DLE_DEBUG_LINE_LENGTH_BAD;
329                 DWARF_SET_ERROR(dbg, error, ret);
330                 goto fail_cleanup;
331         }
332
333         if ((li->li_oplen = malloc(li->li_opbase)) == NULL) {
334                 ret = DW_DLE_MEMORY;
335                 DWARF_SET_ERROR(dbg, error, ret);
336                 goto fail_cleanup;
337         }
338
339         /*
340          * Read in std opcode arg length list. Note that the first
341          * element is not used.
342          */
343         for (i = 1; i < li->li_opbase; i++)
344                 li->li_oplen[i] = dbg->read(ds->ds_data, &offset, 1);
345
346         /*
347          * Check how many strings in the include dir string array.
348          */
349         length = 0;
350         p = ds->ds_data + offset;
351         while (*p != '\0') {
352                 while (*p++ != '\0')
353                         ;
354                 length++;
355         }
356         li->li_inclen = length;
357
358         /* Sanity check. */
359         if (p - ds->ds_data > (int) ds->ds_size) {
360                 ret = DW_DLE_DEBUG_LINE_LENGTH_BAD;
361                 DWARF_SET_ERROR(dbg, error, ret);
362                 goto fail_cleanup;
363         }
364
365         if (length != 0) {
366                 if ((li->li_incdirs = malloc(length * sizeof(char *))) ==
367                     NULL) {
368                         ret = DW_DLE_MEMORY;
369                         DWARF_SET_ERROR(dbg, error, ret);
370                         goto fail_cleanup;
371                 }
372         }
373
374         /* Fill in include dir array. */
375         i = 0;
376         p = ds->ds_data + offset;
377         while (*p != '\0') {
378                 li->li_incdirs[i++] = (char *) p;
379                 while (*p++ != '\0')
380                         ;
381         }
382
383         p++;
384
385         /*
386          * Process file list.
387          */
388         while (*p != '\0') {
389                 ret = _dwarf_lineno_add_file(li, &p, compdir, error, dbg);
390                 if (ret != DW_DLE_NONE)
391                         goto fail_cleanup;
392                 if (p - ds->ds_data > (int) ds->ds_size) {
393                         ret = DW_DLE_DEBUG_LINE_LENGTH_BAD;
394                         DWARF_SET_ERROR(dbg, error, ret);
395                         goto fail_cleanup;
396                 }
397         }
398
399         p++;
400
401         /* Sanity check. */
402         if (p - ds->ds_data - hdroff != li->li_hdrlen) {
403                 ret = DW_DLE_DEBUG_LINE_LENGTH_BAD;
404                 DWARF_SET_ERROR(dbg, error, ret);
405                 goto fail_cleanup;
406         }
407
408         /*
409          * Process line number program.
410          */
411         ret = _dwarf_lineno_run_program(cu, li, p, ds->ds_data + endoff, compdir,
412             error);
413         if (ret != DW_DLE_NONE)
414                 goto fail_cleanup;
415
416         cu->cu_lineinfo = li;
417
418         return (DW_DLE_NONE);
419
420 fail_cleanup:
421
422         STAILQ_FOREACH_SAFE(lf, &li->li_lflist, lf_next, tlf) {
423                 STAILQ_REMOVE(&li->li_lflist, lf, _Dwarf_LineFile, lf_next);
424                 if (lf->lf_fullpath)
425                         free(lf->lf_fullpath);
426                 free(lf);
427         }
428
429         if (li->li_oplen)
430                 free(li->li_oplen);
431         if (li->li_incdirs)
432                 free(li->li_incdirs);
433         free(li);
434
435         return (ret);
436 }
437
438 void
439 _dwarf_lineno_cleanup(Dwarf_LineInfo li)
440 {
441         Dwarf_LineFile lf, tlf;
442         Dwarf_Line ln, tln;
443
444         if (li == NULL)
445                 return;
446         STAILQ_FOREACH_SAFE(lf, &li->li_lflist, lf_next, tlf) {
447                 STAILQ_REMOVE(&li->li_lflist, lf,
448                     _Dwarf_LineFile, lf_next);
449                 if (lf->lf_fullpath)
450                         free(lf->lf_fullpath);
451                 free(lf);
452         }
453         STAILQ_FOREACH_SAFE(ln, &li->li_lnlist, ln_next, tln) {
454                 STAILQ_REMOVE(&li->li_lnlist, ln, _Dwarf_Line,
455                     ln_next);
456                 free(ln);
457         }
458         if (li->li_oplen)
459                 free(li->li_oplen);
460         if (li->li_incdirs)
461                 free(li->li_incdirs);
462         if (li->li_lnarray)
463                 free(li->li_lnarray);
464         if (li->li_lfnarray)
465                 free(li->li_lfnarray);
466         free(li);
467 }
468
469 static int
470 _dwarf_lineno_gen_program(Dwarf_P_Debug dbg, Dwarf_P_Section ds,
471     Dwarf_Rel_Section drs, Dwarf_Error * error)
472 {
473         Dwarf_LineInfo li;
474         Dwarf_Line ln;
475         Dwarf_Unsigned address, file, line, spc;
476         Dwarf_Unsigned addr0, maddr;
477         Dwarf_Signed line0, column;
478         int is_stmt, basic_block;
479         int need_copy;
480         int ret;
481
482 #define RESET_REGISTERS                                         \
483         do {                                                    \
484                 address        = 0;                             \
485                 file           = 1;                             \
486                 line           = 1;                             \
487                 column         = 0;                             \
488                 is_stmt        = li->li_defstmt;                \
489                 basic_block    = 0;                             \
490         } while(0)
491
492         li = dbg->dbgp_lineinfo;
493         maddr = (255 - li->li_opbase) / li->li_lrange;
494
495         RESET_REGISTERS;
496
497         STAILQ_FOREACH(ln, &li->li_lnlist, ln_next) {
498                 if (ln->ln_symndx > 0) {
499                         /*
500                          * Generate DW_LNE_set_address extended op.
501                          */
502                         RCHECK(WRITE_VALUE(0, 1));
503                         RCHECK(WRITE_ULEB128(dbg->dbg_pointer_size + 1));
504                         RCHECK(WRITE_VALUE(DW_LNE_set_address, 1));
505                         RCHECK(_dwarf_reloc_entry_add(dbg, drs, ds,
506                             dwarf_drt_data_reloc, dbg->dbg_pointer_size,
507                             ds->ds_size, ln->ln_symndx, ln->ln_addr,
508                             NULL, error));
509                         address = ln->ln_addr;
510                         continue;
511                 } else if (ln->ln_endseq) {
512                         addr0 = (ln->ln_addr - address) / li->li_minlen;
513                         if (addr0 != 0) {
514                                 RCHECK(WRITE_VALUE(DW_LNS_advance_pc, 1));
515                                 RCHECK(WRITE_ULEB128(addr0));
516                         }
517
518                         /*
519                          * Generate DW_LNE_end_sequence.
520                          */
521                         RCHECK(WRITE_VALUE(0, 1));
522                         RCHECK(WRITE_ULEB128(1));
523                         RCHECK(WRITE_VALUE(DW_LNE_end_sequence, 1));
524                         RESET_REGISTERS;
525                         continue;
526                 }
527
528                 /*
529                  * Generate standard opcodes for file, column, is_stmt or
530                  * basic_block changes.
531                  */
532                 if (ln->ln_fileno != file) {
533                         RCHECK(WRITE_VALUE(DW_LNS_set_file, 1));
534                         RCHECK(WRITE_ULEB128(ln->ln_fileno));
535                         file = ln->ln_fileno;
536                 }
537                 if (ln->ln_column != column) {
538                         RCHECK(WRITE_VALUE(DW_LNS_set_column, 1));
539                         RCHECK(WRITE_ULEB128(ln->ln_column));
540                         column = ln->ln_column;
541                 }
542                 if (ln->ln_stmt != is_stmt) {
543                         RCHECK(WRITE_VALUE(DW_LNS_negate_stmt, 1));
544                         is_stmt = ln->ln_stmt;
545                 }
546                 if (ln->ln_bblock && !basic_block) {
547                         RCHECK(WRITE_VALUE(DW_LNS_set_basic_block, 1));
548                         basic_block = 1;
549                 }
550
551                 /*
552                  * Calculate address and line number change.
553                  */
554                 addr0 = (ln->ln_addr - address) / li->li_minlen;
555                 line0 = ln->ln_lineno - line;
556
557                 if (addr0 == 0 && line0 == 0)
558                         continue;
559
560                 /*
561                  * Check if line delta is with the range and if the special
562                  * opcode can be used.
563                  */
564                 assert(li->li_lbase <= 0);
565                 if (line0 >= li->li_lbase &&
566                     line0 <= li->li_lbase + li->li_lrange - 1) {
567                         spc = (line0 - li->li_lbase) +
568                             (li->li_lrange * addr0) + li->li_opbase;
569                         if (spc <= 255) {
570                                 RCHECK(WRITE_VALUE(spc, 1));
571                                 basic_block = 0;
572                                 goto next_line;
573                         }
574                 }
575
576                 /* Generate DW_LNS_advance_line for line number change. */
577                 if (line0 != 0) {
578                         RCHECK(WRITE_VALUE(DW_LNS_advance_line, 1));
579                         RCHECK(WRITE_SLEB128(line0));
580                         line0 = 0;
581                         need_copy = 1;
582                 } else
583                         need_copy = basic_block;
584
585                 if (addr0 != 0) {
586                         /* See if it can be handled by DW_LNS_const_add_pc. */
587                         spc = (line0 - li->li_lbase) +
588                             (li->li_lrange * (addr0 - maddr)) + li->li_opbase;
589                         if (addr0 >= maddr && spc <= 255) {
590                                 RCHECK(WRITE_VALUE(DW_LNS_const_add_pc, 1));
591                                 RCHECK(WRITE_VALUE(spc, 1));
592                         } else {
593                                 /* Otherwise we use DW_LNS_advance_pc. */
594                                 RCHECK(WRITE_VALUE(DW_LNS_advance_pc, 1));
595                                 RCHECK(WRITE_ULEB128(addr0));
596                         }
597                 }
598
599                 if (need_copy) {
600                         RCHECK(WRITE_VALUE(DW_LNS_copy, 1));
601                         basic_block = 0;
602                 }
603
604         next_line:
605                 address = ln->ln_addr;
606                 line = ln->ln_lineno;
607         }
608
609         return (DW_DLE_NONE);
610
611 gen_fail:
612         return (ret);
613
614 #undef  RESET_REGISTERS
615 }
616
617 static uint8_t
618 _dwarf_get_minlen(Dwarf_P_Debug dbg)
619 {
620
621         assert(dbg != NULL);
622
623         switch (dbg->dbgp_isa) {
624         case DW_ISA_ARM:
625                 return (2);
626         case DW_ISA_X86:
627         case DW_ISA_X86_64:
628                 return (1);
629         default:
630                 return (4);
631         }
632 }
633
634 static uint8_t oplen[] = {0, 1, 1, 1, 1, 0, 0, 0, 1};
635
636 int
637 _dwarf_lineno_gen(Dwarf_P_Debug dbg, Dwarf_Error *error)
638 {
639         Dwarf_LineInfo li;
640         Dwarf_LineFile lf;
641         Dwarf_P_Section ds;
642         Dwarf_Rel_Section drs;
643         Dwarf_Unsigned offset;
644         int i, ret;
645
646         assert(dbg != NULL && dbg->dbgp_lineinfo != NULL);
647
648         li = dbg->dbgp_lineinfo;
649         if (STAILQ_EMPTY(&li->li_lnlist))
650                 return (DW_DLE_NONE);
651
652         li->li_length = 0;
653         li->li_version = 2;
654         li->li_hdrlen = 0;
655         li->li_minlen = _dwarf_get_minlen(dbg);
656         li->li_defstmt = 1;
657         li->li_lbase = -5;
658         li->li_lrange = 14;
659         li->li_opbase = 10;
660
661         /* Create .debug_line section. */
662         if ((ret = _dwarf_section_init(dbg, &ds, ".debug_line", 0, error)) !=
663             DW_DLE_NONE)
664                 return (ret);
665
666         /* Create relocation section for .debug_line */
667         if ((ret = _dwarf_reloc_section_init(dbg, &drs, ds, error)) !=
668             DW_DLE_NONE)
669                 goto gen_fail1;
670
671         /* Length placeholder. (We only use 32-bit DWARF format) */
672         RCHECK(WRITE_VALUE(0, 4));
673
674         /* Write line number dwarf version. (DWARF2) */
675         RCHECK(WRITE_VALUE(li->li_version, 2));
676
677         /* Header length placeholder. */
678         offset = ds->ds_size;
679         RCHECK(WRITE_VALUE(li->li_hdrlen, 4));
680
681         /* Write minimum instruction length. */
682         RCHECK(WRITE_VALUE(li->li_minlen, 1));
683
684         /*
685          * Write initial value for is_stmt. XXX Which default value we
686          * should use?
687          */
688         RCHECK(WRITE_VALUE(li->li_defstmt, 1));
689
690         /*
691          * Write line_base and line_range. FIXME These value needs to be
692          * fine tuned.
693          */
694         RCHECK(WRITE_VALUE(li->li_lbase, 1));
695         RCHECK(WRITE_VALUE(li->li_lrange, 1));
696
697         /* Write opcode_base. (DWARF2) */
698         RCHECK(WRITE_VALUE(li->li_opbase, 1));
699
700         /* Write standard op length array. */
701         RCHECK(WRITE_BLOCK(oplen, sizeof(oplen) / sizeof(oplen[0])));
702
703         /* Write the list of include directories. */
704         for (i = 0; (Dwarf_Unsigned) i < li->li_inclen; i++)
705                 RCHECK(WRITE_STRING(li->li_incdirs[i]));
706         RCHECK(WRITE_VALUE(0, 1));
707
708         /* Write the list of filenames. */
709         STAILQ_FOREACH(lf, &li->li_lflist, lf_next) {
710                 RCHECK(WRITE_STRING(lf->lf_fname));
711                 RCHECK(WRITE_ULEB128(lf->lf_dirndx));
712                 RCHECK(WRITE_ULEB128(lf->lf_mtime));
713                 RCHECK(WRITE_ULEB128(lf->lf_size));
714         }
715         RCHECK(WRITE_VALUE(0, 1));
716
717         /* Fill in the header length. */
718         li->li_hdrlen = ds->ds_size - offset - 4;
719         dbg->write(ds->ds_data, &offset, li->li_hdrlen, 4);
720
721         /* Generate the line number program. */
722         RCHECK(_dwarf_lineno_gen_program(dbg, ds, drs, error));
723
724         /* Fill in the length of this line info. */
725         li->li_length = ds->ds_size - 4;
726         offset = 0;
727         dbg->write(ds->ds_data, &offset, li->li_length, 4);
728
729         /* Notify the creation of .debug_line ELF section. */
730         RCHECK(_dwarf_section_callback(dbg, ds, SHT_PROGBITS, 0, 0, 0, error));
731
732         /* Finalize relocation section for .debug_line. */
733         RCHECK(_dwarf_reloc_section_finalize(dbg, drs, error));
734
735         return (DW_DLE_NONE);
736
737 gen_fail:
738         _dwarf_reloc_section_free(dbg, &drs);
739
740 gen_fail1:
741         _dwarf_section_free(dbg, &ds);
742
743         return (ret);
744 }
745
746 void
747 _dwarf_lineno_pro_cleanup(Dwarf_P_Debug dbg)
748 {
749         Dwarf_LineInfo li;
750         Dwarf_LineFile lf, tlf;
751         Dwarf_Line ln, tln;
752         int i;
753
754         assert(dbg != NULL && dbg->dbg_mode == DW_DLC_WRITE);
755         if (dbg->dbgp_lineinfo == NULL)
756                 return;
757
758         li = dbg->dbgp_lineinfo;
759         STAILQ_FOREACH_SAFE(lf, &li->li_lflist, lf_next, tlf) {
760                 STAILQ_REMOVE(&li->li_lflist, lf, _Dwarf_LineFile,
761                     lf_next);
762                 if (lf->lf_fname)
763                         free(lf->lf_fname);
764                 free(lf);
765         }
766         STAILQ_FOREACH_SAFE(ln, &li->li_lnlist, ln_next, tln) {
767                 STAILQ_REMOVE(&li->li_lnlist, ln, _Dwarf_Line, ln_next);
768                 free(ln);
769         }
770         if (li->li_incdirs) {
771                 for (i = 0; (Dwarf_Unsigned) i < li->li_inclen; i++)
772                         free(li->li_incdirs[i]);
773                 free(li->li_incdirs);
774         }
775         free(li);
776         dbg->dbgp_lineinfo = NULL;
777 }