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