• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Return line number information of CU.
2    Copyright (C) 2004-2010 Red Hat, Inc.
3    This file is part of Red Hat elfutils.
4    Written by Ulrich Drepper <drepper@redhat.com>, 2004.
5 
6    Red Hat elfutils is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by the
8    Free Software Foundation; version 2 of the License.
9 
10    Red Hat elfutils is distributed in the hope that it will be useful, but
11    WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    General Public License for more details.
14 
15    You should have received a copy of the GNU General Public License along
16    with Red Hat elfutils; if not, write to the Free Software Foundation,
17    Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
18 
19    In addition, as a special exception, Red Hat, Inc. gives You the
20    additional right to link the code of Red Hat elfutils with code licensed
21    under any Open Source Initiative certified open source license
22    (http://www.opensource.org/licenses/index.php) which requires the
23    distribution of source code with any binary distribution and to
24    distribute linked combinations of the two.  Non-GPL Code permitted under
25    this exception must only link to the code of Red Hat elfutils through
26    those well defined interfaces identified in the file named EXCEPTION
27    found in the source code files (the "Approved Interfaces").  The files
28    of Non-GPL Code may instantiate templates or use macros or inline
29    functions from the Approved Interfaces without causing the resulting
30    work to be covered by the GNU General Public License.  Only Red Hat,
31    Inc. may make changes or additions to the list of Approved Interfaces.
32    Red Hat's grant of this exception is conditioned upon your not adding
33    any new exceptions.  If you wish to add a new Approved Interface or
34    exception, please contact Red Hat.  You must obey the GNU General Public
35    License in all respects for all of the Red Hat elfutils code and other
36    code used in conjunction with Red Hat elfutils except the Non-GPL Code
37    covered by this exception.  If you modify this file, you may extend this
38    exception to your version of the file, but you are not obligated to do
39    so.  If you do not wish to provide this exception without modification,
40    you must delete this exception statement from your version and license
41    this file solely under the GPL without exception.
42 
43    Red Hat elfutils is an included package of the Open Invention Network.
44    An included package of the Open Invention Network is a package for which
45    Open Invention Network licensees cross-license their patents.  No patent
46    license is granted, either expressly or impliedly, by designation as an
47    included package.  Should you wish to participate in the Open Invention
48    Network licensing program, please visit www.openinventionnetwork.com
49    <http://www.openinventionnetwork.com>.  */
50 
51 #ifdef HAVE_CONFIG_H
52 # include <config.h>
53 #endif
54 
55 #include <assert.h>
56 #include <stdlib.h>
57 #include <string.h>
58 #include "dwarf.h"
59 #include "libdwP.h"
60 
61 
62 struct filelist
63 {
64   Dwarf_Fileinfo info;
65   struct filelist *next;
66 };
67 
68 struct linelist
69 {
70   Dwarf_Line line;
71   struct linelist *next;
72 };
73 
74 
75 /* Compare by Dwarf_Line.addr, given pointers into an array of pointers.  */
76 static int
compare_lines(const void * a,const void * b)77 compare_lines (const void *a, const void *b)
78 {
79   Dwarf_Line *const *p1 = a;
80   Dwarf_Line *const *p2 = b;
81 
82   if ((*p1)->addr == (*p2)->addr)
83     /* An end_sequence marker precedes a normal record at the same address.  */
84     return (*p2)->end_sequence - (*p1)->end_sequence;
85 
86   return (*p1)->addr - (*p2)->addr;
87 }
88 
89 int
dwarf_getsrclines(Dwarf_Die * cudie,Dwarf_Lines ** lines,size_t * nlines)90 dwarf_getsrclines (Dwarf_Die *cudie, Dwarf_Lines **lines, size_t *nlines)
91 {
92   if (unlikely (cudie == NULL
93 		|| INTUSE(dwarf_tag) (cudie) != DW_TAG_compile_unit))
94     return -1;
95 
96   int res = -1;
97 
98   /* Get the information if it is not already known.  */
99   struct Dwarf_CU *const cu = cudie->cu;
100   if (cu->lines == NULL)
101     {
102       /* Failsafe mode: no data found.  */
103       cu->lines = (void *) -1l;
104       cu->files = (void *) -1l;
105 
106       /* The die must have a statement list associated.  */
107       Dwarf_Attribute stmt_list_mem;
108       Dwarf_Attribute *stmt_list = INTUSE(dwarf_attr) (cudie, DW_AT_stmt_list,
109 						       &stmt_list_mem);
110 
111       /* Get the offset into the .debug_line section.  NB: this call
112 	 also checks whether the previous dwarf_attr call failed.  */
113       const unsigned char *lineendp;
114       const unsigned char *linep
115 	= __libdw_formptr (stmt_list, IDX_debug_line, DWARF_E_NO_DEBUG_LINE,
116 			   (unsigned char **) &lineendp, NULL);
117       if (linep == NULL)
118 	goto out;
119 
120       /* Get the compilation directory.  */
121       Dwarf_Attribute compdir_attr_mem;
122       Dwarf_Attribute *compdir_attr = INTUSE(dwarf_attr) (cudie,
123 							  DW_AT_comp_dir,
124 							  &compdir_attr_mem);
125       const char *comp_dir = INTUSE(dwarf_formstring) (compdir_attr);
126 
127       if (unlikely (linep + 4 > lineendp))
128 	{
129 	invalid_data:
130 	  __libdw_seterrno (DWARF_E_INVALID_DEBUG_LINE);
131 	  goto out;
132 	}
133 
134       Dwarf *dbg = cu->dbg;
135       Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, linep);
136       unsigned int length = 4;
137       if (unlikely (unit_length == DWARF3_LENGTH_64_BIT))
138 	{
139 	  if (unlikely (linep + 8 > lineendp))
140 	    goto invalid_data;
141 	  unit_length = read_8ubyte_unaligned_inc (dbg, linep);
142 	  length = 8;
143 	}
144 
145       /* Check whether we have enough room in the section.  */
146       if (unit_length < 2 + length + 5 * 1
147 	  || unlikely (linep + unit_length > lineendp))
148 	goto invalid_data;
149       lineendp = linep + unit_length;
150 
151       /* The next element of the header is the version identifier.  */
152       uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, linep);
153       if (unlikely (version < 2) || unlikely (version > 4))
154 	{
155 	  __libdw_seterrno (DWARF_E_VERSION);
156 	  goto out;
157 	}
158 
159       /* Next comes the header length.  */
160       Dwarf_Word header_length;
161       if (length == 4)
162 	header_length = read_4ubyte_unaligned_inc (dbg, linep);
163       else
164 	header_length = read_8ubyte_unaligned_inc (dbg, linep);
165       const unsigned char *header_start = linep;
166 
167       /* Next the minimum instruction length.  */
168       uint_fast8_t minimum_instr_len = *linep++;
169 
170       /* Next the maximum operations per instruction, in version 4 format.  */
171       uint_fast8_t max_ops_per_instr = 1;
172       if (version >= 4)
173 	{
174 	  if (unlikely (lineendp - linep < 5))
175 	    goto invalid_data;
176 	  max_ops_per_instr = *linep++;
177 	  if (unlikely (max_ops_per_instr == 0))
178 	    goto invalid_data;
179 	}
180 
181       /* Then the flag determining the default value of the is_stmt
182 	 register.  */
183       uint_fast8_t default_is_stmt = *linep++;
184 
185       /* Now the line base.  */
186       int_fast8_t line_base = (int8_t) *linep++;
187 
188       /* And the line range.  */
189       uint_fast8_t line_range = *linep++;
190 
191       /* The opcode base.  */
192       uint_fast8_t opcode_base = *linep++;
193 
194       /* Remember array with the standard opcode length (-1 to account for
195 	 the opcode with value zero not being mentioned).  */
196       const uint8_t *standard_opcode_lengths = linep - 1;
197       if (unlikely (lineendp - linep < opcode_base - 1))
198 	goto invalid_data;
199       linep += opcode_base - 1;
200 
201       /* First comes the list of directories.  Add the compilation
202 	 directory first since the index zero is used for it.  */
203       struct dirlist
204       {
205 	const char *dir;
206 	size_t len;
207 	struct dirlist *next;
208       } comp_dir_elem =
209 	{
210 	  .dir = comp_dir,
211 	  .len = comp_dir ? strlen (comp_dir) : 0,
212 	  .next = NULL
213 	};
214       struct dirlist *dirlist = &comp_dir_elem;
215       unsigned int ndirlist = 1;
216 
217       // XXX Directly construct array to conserve memory?
218       while (*linep != 0)
219 	{
220 	  struct dirlist *new_dir =
221 	    (struct dirlist *) alloca (sizeof (*new_dir));
222 
223 	  new_dir->dir = (char *) linep;
224 	  uint8_t *endp = memchr (linep, '\0', lineendp - linep);
225 	  if (endp == NULL)
226 	    goto invalid_data;
227 	  new_dir->len = endp - linep;
228 	  new_dir->next = dirlist;
229 	  dirlist = new_dir;
230 	  ++ndirlist;
231 	  linep = endp + 1;
232 	}
233       /* Skip the final NUL byte.  */
234       ++linep;
235 
236       /* Rearrange the list in array form.  */
237       struct dirlist **dirarray
238 	= (struct dirlist **) alloca (ndirlist * sizeof (*dirarray));
239       for (unsigned int n = ndirlist; n-- > 0; dirlist = dirlist->next)
240 	dirarray[n] = dirlist;
241 
242       /* Now read the files.  */
243       struct filelist null_file =
244 	{
245 	  .info =
246 	  {
247 	    .name = "???",
248 	    .mtime = 0,
249 	    .length = 0
250 	  },
251 	  .next = NULL
252 	};
253       struct filelist *filelist = &null_file;
254       unsigned int nfilelist = 1;
255 
256       if (unlikely (linep >= lineendp))
257 	goto invalid_data;
258       while (*linep != 0)
259 	{
260 	  struct filelist *new_file =
261 	    (struct filelist *) alloca (sizeof (*new_file));
262 
263 	  /* First comes the file name.  */
264 	  char *fname = (char *) linep;
265 	  uint8_t *endp = memchr (fname, '\0', lineendp - linep);
266 	  if (endp == NULL)
267 	    goto invalid_data;
268 	  size_t fnamelen = endp - (uint8_t *) fname;
269 	  linep = endp + 1;
270 
271 	  /* Then the index.  */
272 	  Dwarf_Word diridx;
273 	  get_uleb128 (diridx, linep);
274 	  if (unlikely (diridx >= ndirlist))
275 	    {
276 	      __libdw_seterrno (DWARF_E_INVALID_DIR_IDX);
277 	      goto out;
278 	    }
279 
280 	  if (*fname == '/')
281 	    /* It's an absolute path.  */
282 	    new_file->info.name = fname;
283 	  else
284 	    {
285 	      new_file->info.name = libdw_alloc (dbg, char, 1,
286 						 dirarray[diridx]->len + 1
287 						 + fnamelen + 1);
288               char *cp = new_file->info.name;
289 
290               if (dirarray[diridx]->dir != NULL)
291 		{
292 		  /* This value could be NULL in case the DW_AT_comp_dir
293 		     was not present.  We cannot do much in this case.
294 		     The easiest thing is to convert the path in an
295                    absolute path.  */
296 		  cp = stpcpy (cp, dirarray[diridx]->dir);
297 		}
298               *cp++ = '/';
299               strcpy (cp, fname);
300 	      assert (strlen (new_file->info.name)
301 		      < dirarray[diridx]->len + 1 + fnamelen + 1);
302             }
303 
304 	  /* Next comes the modification time.  */
305 	  get_uleb128 (new_file->info.mtime, linep);
306 
307 	  /* Finally the length of the file.  */
308 	  get_uleb128 (new_file->info.length, linep);
309 
310 	  new_file->next = filelist;
311 	  filelist = new_file;
312 	  ++nfilelist;
313 	}
314       /* Skip the final NUL byte.  */
315       ++linep;
316 
317       /* Consistency check.  */
318       if (unlikely (linep != header_start + header_length))
319 	{
320 	  __libdw_seterrno (DWARF_E_INVALID_DWARF);
321 	  goto out;
322 	}
323 
324         /* We are about to process the statement program.  Initialize the
325 	   state machine registers (see 6.2.2 in the v2.1 specification).  */
326       Dwarf_Word addr = 0;
327       unsigned int op_index = 0;
328       unsigned int file = 1;
329       int line = 1;
330       unsigned int column = 0;
331       uint_fast8_t is_stmt = default_is_stmt;
332       bool basic_block = false;
333       bool prologue_end = false;
334       bool epilogue_begin = false;
335       unsigned int isa = 0;
336       unsigned int discriminator = 0;
337 
338       /* Apply the "operation advance" from a special opcode
339 	 or DW_LNS_advance_pc (as per DWARF4 6.2.5.1).  */
340       inline void advance_pc (unsigned int op_advance)
341       {
342 	addr += minimum_instr_len * ((op_index + op_advance)
343 				     / max_ops_per_instr);
344 	op_index = (op_index + op_advance) % max_ops_per_instr;
345       }
346 
347       /* Process the instructions.  */
348       struct linelist *linelist = NULL;
349       unsigned int nlinelist = 0;
350 
351       /* Adds a new line to the matrix.
352 	 We cannot simply define a function because we want to use alloca.  */
353 #define NEW_LINE(end_seq)						\
354       do {								\
355 	if (unlikely (add_new_line (alloca (sizeof (struct linelist)),	\
356 				    end_seq)))				\
357 	  goto invalid_data;						\
358       } while (0)
359 
360       inline bool add_new_line (struct linelist *new_line, bool end_sequence)
361       {
362 	/* Set the line information.  For some fields we use bitfields,
363 	   so we would lose information if the encoded values are too large.
364 	   Check just for paranoia, and call the data "invalid" if it
365 	   violates our assumptions on reasonable limits for the values.  */
366 #define SET(field)							      \
367 	do {								      \
368 	  new_line->line.field = field;					      \
369 	  if (unlikely (new_line->line.field != field))			      \
370 	    return true;						      \
371         } while (0)
372 
373 	SET (addr);
374 	SET (op_index);
375 	SET (file);
376 	SET (line);
377 	SET (column);
378 	SET (is_stmt);
379 	SET (basic_block);
380 	SET (end_sequence);
381 	SET (prologue_end);
382 	SET (epilogue_begin);
383 	SET (isa);
384 	SET (discriminator);
385 
386 #undef SET
387 
388 	new_line->next = linelist;
389 	linelist = new_line;
390 	++nlinelist;
391 
392 	return false;
393       }
394 
395       while (linep < lineendp)
396 	{
397 	  unsigned int opcode;
398 	  unsigned int u128;
399 	  int s128;
400 
401 	  /* Read the opcode.  */
402 	  opcode = *linep++;
403 
404 	  /* Is this a special opcode?  */
405 	  if (likely (opcode >= opcode_base))
406 	    {
407 	      /* Yes.  Handling this is quite easy since the opcode value
408 		 is computed with
409 
410 		 opcode = (desired line increment - line_base)
411 		           + (line_range * address advance) + opcode_base
412 	      */
413 	      int line_increment = (line_base
414 				    + (opcode - opcode_base) % line_range);
415 
416 	      /* Perform the increments.  */
417 	      line += line_increment;
418 	      advance_pc ((opcode - opcode_base) / line_range);
419 
420 	      /* Add a new line with the current state machine values.  */
421 	      NEW_LINE (0);
422 
423 	      /* Reset the flags.  */
424 	      basic_block = false;
425 	      prologue_end = false;
426 	      epilogue_begin = false;
427 	      discriminator = 0;
428 	    }
429 	  else if (opcode == 0)
430 	    {
431 	      /* This an extended opcode.  */
432 	      if (unlikely (lineendp - linep < 2))
433 		goto invalid_data;
434 
435 	      /* The length.  */
436 	      uint_fast8_t len = *linep++;
437 
438 	      if (unlikely ((size_t) (lineendp - linep) < len))
439 		goto invalid_data;
440 
441 	      /* The sub-opcode.  */
442 	      opcode = *linep++;
443 
444 	      switch (opcode)
445 		{
446 		case DW_LNE_end_sequence:
447 		  /* Add a new line with the current state machine values.
448 		     The is the end of the sequence.  */
449 		  NEW_LINE (1);
450 
451 		  /* Reset the registers.  */
452 		  addr = 0;
453 		  op_index = 0;
454 		  file = 1;
455 		  line = 1;
456 		  column = 0;
457 		  is_stmt = default_is_stmt;
458 		  basic_block = false;
459 		  prologue_end = false;
460 		  epilogue_begin = false;
461 		  isa = 0;
462 		  discriminator = 0;
463 		  break;
464 
465 		case DW_LNE_set_address:
466 		  /* The value is an address.  The size is defined as
467 		     apporiate for the target machine.  We use the
468 		     address size field from the CU header.  */
469 		  op_index = 0;
470 		  if (unlikely (lineendp - linep < cu->address_size))
471 		    goto invalid_data;
472 		  if (__libdw_read_address_inc (dbg, IDX_debug_line, &linep,
473 						cu->address_size, &addr))
474 		    goto out;
475 		  break;
476 
477 		case DW_LNE_define_file:
478 		  {
479 		    char *fname = (char *) linep;
480 		    uint8_t *endp = memchr (linep, '\0', lineendp - linep);
481 		    if (endp == NULL)
482 		      goto invalid_data;
483 		    size_t fnamelen = endp - linep;
484 		    linep = endp + 1;
485 
486 		    unsigned int diridx;
487 		    get_uleb128 (diridx, linep);
488 		    Dwarf_Word mtime;
489 		    get_uleb128 (mtime, linep);
490 		    Dwarf_Word filelength;
491 		    get_uleb128 (filelength, linep);
492 
493 		    struct filelist *new_file =
494 		      (struct filelist *) alloca (sizeof (*new_file));
495 		    if (fname[0] == '/')
496 		      new_file->info.name = fname;
497 		    else
498 		      {
499 			new_file->info.name =
500 			  libdw_alloc (dbg, char, 1, (dirarray[diridx]->len + 1
501 						      + fnamelen + 1));
502 			char *cp = new_file->info.name;
503 
504 			if (dirarray[diridx]->dir != NULL)
505 			  /* This value could be NULL in case the
506 			     DW_AT_comp_dir was not present.  We
507 			     cannot do much in this case.  The easiest
508 			     thing is to convert the path in an
509 			     absolute path.  */
510 			  cp = stpcpy (cp, dirarray[diridx]->dir);
511 			*cp++ = '/';
512 			strcpy (cp, fname);
513 		      }
514 
515 		    new_file->info.mtime = mtime;
516 		    new_file->info.length = filelength;
517 		    new_file->next = filelist;
518 		    filelist = new_file;
519 		    ++nfilelist;
520 		  }
521 		  break;
522 
523 		case DW_LNE_set_discriminator:
524 		  /* Takes one ULEB128 parameter, the discriminator.  */
525 		  if (unlikely (standard_opcode_lengths[opcode] != 1))
526 		    goto invalid_data;
527 
528 		  get_uleb128 (discriminator, linep);
529 		  break;
530 
531 		default:
532 		  /* Unknown, ignore it.  */
533 		  if (unlikely ((size_t) (lineendp - (linep - 1)) < len))
534 		    goto invalid_data;
535 		  linep += len - 1;
536 		  break;
537 		}
538 	    }
539 	  else if (opcode <= DW_LNS_set_isa)
540 	    {
541 	      /* This is a known standard opcode.  */
542 	      switch (opcode)
543 		{
544 		case DW_LNS_copy:
545 		  /* Takes no argument.  */
546 		  if (unlikely (standard_opcode_lengths[opcode] != 0))
547 		    goto invalid_data;
548 
549 		  /* Add a new line with the current state machine values.  */
550 		  NEW_LINE (0);
551 
552 		  /* Reset the flags.  */
553 		  basic_block = false;
554 		  prologue_end = false;
555 		  epilogue_begin = false;
556 		  discriminator = 0;
557 		  break;
558 
559 		case DW_LNS_advance_pc:
560 		  /* Takes one uleb128 parameter which is added to the
561 		     address.  */
562 		  if (unlikely (standard_opcode_lengths[opcode] != 1))
563 		    goto invalid_data;
564 
565 		  get_uleb128 (u128, linep);
566 		  advance_pc (u128);
567 		  break;
568 
569 		case DW_LNS_advance_line:
570 		  /* Takes one sleb128 parameter which is added to the
571 		     line.  */
572 		  if (unlikely (standard_opcode_lengths[opcode] != 1))
573 		    goto invalid_data;
574 
575 		  get_sleb128 (s128, linep);
576 		  line += s128;
577 		  break;
578 
579 		case DW_LNS_set_file:
580 		  /* Takes one uleb128 parameter which is stored in file.  */
581 		  if (unlikely (standard_opcode_lengths[opcode] != 1))
582 		    goto invalid_data;
583 
584 		  get_uleb128 (u128, linep);
585 		  file = u128;
586 		  break;
587 
588 		case DW_LNS_set_column:
589 		  /* Takes one uleb128 parameter which is stored in column.  */
590 		  if (unlikely (standard_opcode_lengths[opcode] != 1))
591 		    goto invalid_data;
592 
593 		  get_uleb128 (u128, linep);
594 		  column = u128;
595 		  break;
596 
597 		case DW_LNS_negate_stmt:
598 		  /* Takes no argument.  */
599 		  if (unlikely (standard_opcode_lengths[opcode] != 0))
600 		    goto invalid_data;
601 
602 		  is_stmt = 1 - is_stmt;
603 		  break;
604 
605 		case DW_LNS_set_basic_block:
606 		  /* Takes no argument.  */
607 		  if (unlikely (standard_opcode_lengths[opcode] != 0))
608 		    goto invalid_data;
609 
610 		  basic_block = true;
611 		  break;
612 
613 		case DW_LNS_const_add_pc:
614 		  /* Takes no argument.  */
615 		  if (unlikely (standard_opcode_lengths[opcode] != 0))
616 		    goto invalid_data;
617 
618 		  advance_pc ((255 - opcode_base) / line_range);
619 		  break;
620 
621 		case DW_LNS_fixed_advance_pc:
622 		  /* Takes one 16 bit parameter which is added to the
623 		     address.  */
624 		  if (unlikely (standard_opcode_lengths[opcode] != 1)
625 		      || unlikely (lineendp - linep < 2))
626 		    goto invalid_data;
627 
628 		  addr += read_2ubyte_unaligned_inc (dbg, linep);
629 		  op_index = 0;
630 		  break;
631 
632 		case DW_LNS_set_prologue_end:
633 		  /* Takes no argument.  */
634 		  if (unlikely (standard_opcode_lengths[opcode] != 0))
635 		    goto invalid_data;
636 
637 		  prologue_end = true;
638 		  break;
639 
640 		case DW_LNS_set_epilogue_begin:
641 		  /* Takes no argument.  */
642 		  if (unlikely (standard_opcode_lengths[opcode] != 0))
643 		    goto invalid_data;
644 
645 		  epilogue_begin = true;
646 		  break;
647 
648 		case DW_LNS_set_isa:
649 		  /* Takes one uleb128 parameter which is stored in isa.  */
650 		  if (unlikely (standard_opcode_lengths[opcode] != 1))
651 		    goto invalid_data;
652 
653 		  get_uleb128 (isa, linep);
654 		  break;
655 		}
656 	    }
657 	  else
658 	    {
659 	      /* This is a new opcode the generator but not we know about.
660 		 Read the parameters associated with it but then discard
661 		 everything.  Read all the parameters for this opcode.  */
662 	      for (int n = standard_opcode_lengths[opcode]; n > 0; --n)
663 		get_uleb128 (u128, linep);
664 
665 	      /* Next round, ignore this opcode.  */
666 	      continue;
667 	    }
668 	}
669 
670       /* Put all the files in an array.  */
671       Dwarf_Files *files = libdw_alloc (dbg, Dwarf_Files,
672 					sizeof (Dwarf_Files)
673 					+ nfilelist * sizeof (Dwarf_Fileinfo)
674 					+ (ndirlist + 1) * sizeof (char *),
675 					1);
676       const char **dirs = (void *) &files->info[nfilelist];
677 
678       files->nfiles = nfilelist;
679       while (nfilelist-- > 0)
680 	{
681 	  files->info[nfilelist] = filelist->info;
682 	  filelist = filelist->next;
683 	}
684       assert (filelist == NULL);
685 
686       /* Put all the directory strings in an array.  */
687       files->ndirs = ndirlist;
688       for (unsigned int i = 0; i < ndirlist; ++i)
689 	dirs[i] = dirarray[i]->dir;
690       dirs[ndirlist] = NULL;
691 
692       /* Remember the referring CU.  */
693       files->cu = cu;
694 
695       /* Make the file data structure available through the CU.  */
696       cu->files = files;
697 
698       void *buf = libdw_alloc (dbg, Dwarf_Lines, (sizeof (Dwarf_Lines)
699 						  + (sizeof (Dwarf_Line)
700 						     * nlinelist)), 1);
701 
702       /* First use the buffer for the pointers, and sort the entries.
703 	 We'll write the pointers in the end of the buffer, and then
704 	 copy into the buffer from the beginning so the overlap works.  */
705       assert (sizeof (Dwarf_Line) >= sizeof (Dwarf_Line *));
706       Dwarf_Line **sortlines = (buf + sizeof (Dwarf_Lines)
707 				+ ((sizeof (Dwarf_Line)
708 				    - sizeof (Dwarf_Line *)) * nlinelist));
709 
710       /* The list is in LIFO order and usually they come in clumps with
711 	 ascending addresses.  So fill from the back to probably start with
712 	 runs already in order before we sort.  */
713       unsigned int i = nlinelist;
714       while (i-- > 0)
715 	{
716 	  sortlines[i] = &linelist->line;
717 	  linelist = linelist->next;
718 	}
719       assert (linelist == NULL);
720 
721       /* Sort by ascending address.  */
722       qsort (sortlines, nlinelist, sizeof sortlines[0], &compare_lines);
723 
724       /* Now that they are sorted, put them in the final array.
725 	 The buffers overlap, so we've clobbered the early elements
726 	 of SORTLINES by the time we're reading the later ones.  */
727       cu->lines = buf;
728       cu->lines->nlines = nlinelist;
729       for (i = 0; i < nlinelist; ++i)
730 	{
731 	  cu->lines->info[i] = *sortlines[i];
732 	  cu->lines->info[i].files = files;
733 	}
734 
735       /* Success.  */
736       res = 0;
737     }
738   else if (cu->lines != (void *) -1l)
739     /* We already have the information.  */
740     res = 0;
741 
742   if (likely (res == 0))
743     {
744       *lines = cu->lines;
745       *nlines = cu->lines->nlines;
746     }
747  out:
748 
749   // XXX Eventually: unlocking here.
750 
751   return res;
752 }
753 INTDEF(dwarf_getsrclines)
754