blob: 9b3c97af4ea96c333a26b5cd400bb8f9bfda9d9d [file] [log] [blame]
The Android Open Source Project441f72d2009-03-03 19:29:28 -08001/* Return line number information of CU.
Ben Chengcc6695e2012-03-07 23:04:02 -08002 Copyright (C) 2004, 2005, 2007, 2008 Red Hat, Inc.
3 This file is part of Red Hat elfutils.
The Android Open Source Project441f72d2009-03-03 19:29:28 -08004 Written by Ulrich Drepper <drepper@redhat.com>, 2004.
5
Ben Chengcc6695e2012-03-07 23:04:02 -08006 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.
The Android Open Source Project441f72d2009-03-03 19:29:28 -08009
Ben Chengcc6695e2012-03-07 23:04:02 -080010 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>. */
The Android Open Source Project441f72d2009-03-03 19:29:28 -080050
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
62struct filelist
63{
64 Dwarf_Fileinfo info;
65 struct filelist *next;
66};
67
68struct linelist
69{
70 Dwarf_Line line;
71 struct linelist *next;
72};
73
74
Ben Chengcc6695e2012-03-07 23:04:02 -080075/* Compare by Dwarf_Line.addr, given pointers into an array of pointers. */
76static int
77compare_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
90/* Adds a new line to the matrix. We cannot define a function because
The Android Open Source Project441f72d2009-03-03 19:29:28 -080091 we want to use alloca. */
92#define NEW_LINE(end_seq) \
93 do { \
94 /* Add the new line. */ \
95 new_line = (struct linelist *) alloca (sizeof (struct linelist)); \
96 \
97 /* Set the line information. */ \
98 new_line->line.addr = address; \
99 new_line->line.file = file; \
100 new_line->line.line = line; \
101 new_line->line.column = column; \
102 new_line->line.is_stmt = is_stmt; \
103 new_line->line.basic_block = basic_block; \
104 new_line->line.end_sequence = end_seq; \
105 new_line->line.prologue_end = prologue_end; \
106 new_line->line.epilogue_begin = epilogue_begin; \
107 \
108 new_line->next = linelist; \
109 linelist = new_line; \
110 ++nlinelist; \
111 } while (0)
112
113
114int
115dwarf_getsrclines (Dwarf_Die *cudie, Dwarf_Lines **lines, size_t *nlines)
116{
Ben Chengcc6695e2012-03-07 23:04:02 -0800117 if (unlikely (cudie == NULL
118 || INTUSE(dwarf_tag) (cudie) != DW_TAG_compile_unit))
The Android Open Source Project441f72d2009-03-03 19:29:28 -0800119 return -1;
120
121 int res = -1;
122
123 /* Get the information if it is not already known. */
124 struct Dwarf_CU *const cu = cudie->cu;
125 if (cu->lines == NULL)
126 {
127 /* Failsafe mode: no data found. */
128 cu->lines = (void *) -1l;
129 cu->files = (void *) -1l;
130
131 /* The die must have a statement list associated. */
132 Dwarf_Attribute stmt_list_mem;
Ben Chengcc6695e2012-03-07 23:04:02 -0800133 Dwarf_Attribute *stmt_list = INTUSE(dwarf_attr) (cudie, DW_AT_stmt_list,
134 &stmt_list_mem);
The Android Open Source Project441f72d2009-03-03 19:29:28 -0800135
136 /* Get the offset into the .debug_line section. NB: this call
137 also checks whether the previous dwarf_attr call failed. */
138 Dwarf_Word offset;
Ben Chengcc6695e2012-03-07 23:04:02 -0800139 if (INTUSE(dwarf_formudata) (stmt_list, &offset) != 0)
The Android Open Source Project441f72d2009-03-03 19:29:28 -0800140 goto out;
141
142 Dwarf *dbg = cu->dbg;
143 if (dbg->sectiondata[IDX_debug_line] == NULL)
144 {
145 __libdw_seterrno (DWARF_E_NO_DEBUG_LINE);
146 goto out;
147 }
Ben Chengcc6695e2012-03-07 23:04:02 -0800148 const uint8_t *linep = dbg->sectiondata[IDX_debug_line]->d_buf + offset;
149 const uint8_t *lineendp = (dbg->sectiondata[IDX_debug_line]->d_buf
150 + dbg->sectiondata[IDX_debug_line]->d_size);
The Android Open Source Project441f72d2009-03-03 19:29:28 -0800151
152 /* Get the compilation directory. */
153 Dwarf_Attribute compdir_attr_mem;
Ben Chengcc6695e2012-03-07 23:04:02 -0800154 Dwarf_Attribute *compdir_attr = INTUSE(dwarf_attr) (cudie,
155 DW_AT_comp_dir,
156 &compdir_attr_mem);
157 const char *comp_dir = INTUSE(dwarf_formstring) (compdir_attr);
The Android Open Source Project441f72d2009-03-03 19:29:28 -0800158
159 if (unlikely (linep + 4 > lineendp))
160 {
161 invalid_data:
162 __libdw_seterrno (DWARF_E_INVALID_DEBUG_LINE);
163 goto out;
164 }
165 Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, linep);
166 unsigned int length = 4;
Ben Chengcc6695e2012-03-07 23:04:02 -0800167 if (unlikely (unit_length == DWARF3_LENGTH_64_BIT))
The Android Open Source Project441f72d2009-03-03 19:29:28 -0800168 {
169 if (unlikely (linep + 8 > lineendp))
170 goto invalid_data;
171 unit_length = read_8ubyte_unaligned_inc (dbg, linep);
172 length = 8;
173 }
174
175 /* Check whether we have enough room in the section. */
176 if (unit_length < 2 + length + 5 * 1
177 || unlikely (linep + unit_length > lineendp))
178 goto invalid_data;
179 lineendp = linep + unit_length;
180
181 /* The next element of the header is the version identifier. */
182 uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, linep);
Ben Chengcc6695e2012-03-07 23:04:02 -0800183 if (unlikely (version > DWARF_VERSION))
The Android Open Source Project441f72d2009-03-03 19:29:28 -0800184 {
185 __libdw_seterrno (DWARF_E_VERSION);
186 goto out;
187 }
188
189 /* Next comes the header length. */
190 Dwarf_Word header_length;
191 if (length == 4)
192 header_length = read_4ubyte_unaligned_inc (dbg, linep);
193 else
194 header_length = read_8ubyte_unaligned_inc (dbg, linep);
Ben Chengcc6695e2012-03-07 23:04:02 -0800195 const unsigned char *header_start = linep;
The Android Open Source Project441f72d2009-03-03 19:29:28 -0800196
197 /* Next the minimum instruction length. */
198 uint_fast8_t minimum_instr_len = *linep++;
199
200 /* Then the flag determining the default value of the is_stmt
201 register. */
202 uint_fast8_t default_is_stmt = *linep++;
203
204 /* Now the line base. */
205 int_fast8_t line_base = *((int_fast8_t *) linep);
206 ++linep;
207
208 /* And the line range. */
209 uint_fast8_t line_range = *linep++;
210
211 /* The opcode base. */
212 uint_fast8_t opcode_base = *linep++;
213
214 /* Remember array with the standard opcode length (-1 to account for
215 the opcode with value zero not being mentioned). */
Ben Chengcc6695e2012-03-07 23:04:02 -0800216 const uint8_t *standard_opcode_lengths = linep - 1;
The Android Open Source Project441f72d2009-03-03 19:29:28 -0800217 linep += opcode_base - 1;
218 if (unlikely (linep >= lineendp))
219 goto invalid_data;
220
221 /* First comes the list of directories. Add the compilation
222 directory first since the index zero is used for it. */
223 struct dirlist
224 {
225 const char *dir;
226 size_t len;
227 struct dirlist *next;
228 } comp_dir_elem =
229 {
230 .dir = comp_dir,
231 .len = comp_dir ? strlen (comp_dir) : 0,
232 .next = NULL
233 };
234 struct dirlist *dirlist = &comp_dir_elem;
235 unsigned int ndirlist = 1;
236
237 // XXX Directly construct array to conserve memory?
238 while (*linep != 0)
239 {
240 struct dirlist *new_dir =
241 (struct dirlist *) alloca (sizeof (*new_dir));
242
243 new_dir->dir = (char *) linep;
244 uint8_t *endp = memchr (linep, '\0', lineendp - linep);
245 if (endp == NULL)
246 goto invalid_data;
247 new_dir->len = endp - linep;
248 new_dir->next = dirlist;
249 dirlist = new_dir;
250 ++ndirlist;
251 linep = endp + 1;
252 }
253 /* Skip the final NUL byte. */
254 ++linep;
255
256 /* Rearrange the list in array form. */
257 struct dirlist **dirarray
258 = (struct dirlist **) alloca (ndirlist * sizeof (*dirarray));
Ben Chengcc6695e2012-03-07 23:04:02 -0800259 for (unsigned int n = ndirlist; n-- > 0; dirlist = dirlist->next)
260 dirarray[n] = dirlist;
The Android Open Source Project441f72d2009-03-03 19:29:28 -0800261
Ben Chengcc6695e2012-03-07 23:04:02 -0800262 /* Now read the files. */
The Android Open Source Project441f72d2009-03-03 19:29:28 -0800263 struct filelist null_file =
264 {
265 .info =
266 {
267 .name = "???",
268 .mtime = 0,
269 .length = 0
270 },
271 .next = NULL
272 };
273 struct filelist *filelist = &null_file;
274 unsigned int nfilelist = 1;
275
276 if (unlikely (linep >= lineendp))
277 goto invalid_data;
278 while (*linep != 0)
279 {
280 struct filelist *new_file =
281 (struct filelist *) alloca (sizeof (*new_file));
282
283 /* First comes the file name. */
284 char *fname = (char *) linep;
285 uint8_t *endp = memchr (fname, '\0', lineendp - linep);
286 if (endp == NULL)
287 goto invalid_data;
288 size_t fnamelen = endp - (uint8_t *) fname;
289 linep = endp + 1;
290
291 /* Then the index. */
292 Dwarf_Word diridx;
293 get_uleb128 (diridx, linep);
294 if (unlikely (diridx >= ndirlist))
295 {
296 __libdw_seterrno (DWARF_E_INVALID_DIR_IDX);
297 goto out;
298 }
299
300 if (*fname == '/')
301 /* It's an absolute path. */
302 new_file->info.name = fname;
303 else
304 {
305 new_file->info.name = libdw_alloc (dbg, char, 1,
306 dirarray[diridx]->len + 1
307 + fnamelen + 1);
308 char *cp = new_file->info.name;
309
310 if (dirarray[diridx]->dir != NULL)
311 {
312 /* This value could be NULL in case the DW_AT_comp_dir
313 was not present. We cannot do much in this case.
314 The easiest thing is to convert the path in an
315 absolute path. */
316 cp = stpcpy (cp, dirarray[diridx]->dir);
317 }
318 *cp++ = '/';
319 strcpy (cp, fname);
320 assert (strlen (new_file->info.name)
321 < dirarray[diridx]->len + 1 + fnamelen + 1);
322 }
323
324 /* Next comes the modification time. */
325 get_uleb128 (new_file->info.mtime, linep);
326
327 /* Finally the length of the file. */
328 get_uleb128 (new_file->info.length, linep);
329
330 new_file->next = filelist;
331 filelist = new_file;
332 ++nfilelist;
333 }
334 /* Skip the final NUL byte. */
335 ++linep;
336
337 /* Consistency check. */
338 if (unlikely (linep != header_start + header_length))
339 {
340 __libdw_seterrno (DWARF_E_INVALID_DWARF);
341 goto out;
342 }
343
344 /* We are about to process the statement program. Initialize the
345 state machine registers (see 6.2.2 in the v2.1 specification). */
346 Dwarf_Word address = 0;
347 size_t file = 1;
348 size_t line = 1;
349 size_t column = 0;
350 uint_fast8_t is_stmt = default_is_stmt;
351 int basic_block = 0;
352 int prologue_end = 0;
353 int epilogue_begin = 0;
354
355 /* Process the instructions. */
356 struct linelist *linelist = NULL;
357 unsigned int nlinelist = 0;
358 while (linep < lineendp)
359 {
360 struct linelist *new_line;
361 unsigned int opcode;
362 unsigned int u128;
363 int s128;
364
365 /* Read the opcode. */
366 opcode = *linep++;
367
368 /* Is this a special opcode? */
369 if (likely (opcode >= opcode_base))
370 {
371 /* Yes. Handling this is quite easy since the opcode value
372 is computed with
373
374 opcode = (desired line increment - line_base)
375 + (line_range * address advance) + opcode_base
376 */
377 int line_increment = (line_base
378 + (opcode - opcode_base) % line_range);
379 unsigned int address_increment = (minimum_instr_len
380 * ((opcode - opcode_base)
381 / line_range));
382
383 /* Perform the increments. */
384 line += line_increment;
385 address += address_increment;
386
387 /* Add a new line with the current state machine values. */
388 NEW_LINE (0);
389
390 /* Reset the flags. */
391 basic_block = 0;
392 prologue_end = 0;
393 epilogue_begin = 0;
394 }
395 else if (opcode == 0)
396 {
397 /* This an extended opcode. */
398 if (unlikely (linep + 2 > lineendp))
399 goto invalid_data;
400
401 /* The length. */
402 unsigned int len = *linep++;
403
404 if (unlikely (linep + len > lineendp))
405 goto invalid_data;
406
407 /* The sub-opcode. */
408 opcode = *linep++;
409
410 switch (opcode)
411 {
412 case DW_LNE_end_sequence:
413 /* Add a new line with the current state machine values.
414 The is the end of the sequence. */
415 NEW_LINE (1);
416
417 /* Reset the registers. */
418 address = 0;
419 file = 1;
420 line = 1;
421 column = 0;
422 is_stmt = default_is_stmt;
423 basic_block = 0;
424 prologue_end = 0;
425 epilogue_begin = 0;
426 break;
427
428 case DW_LNE_set_address:
429 /* The value is an address. The size is defined as
430 apporiate for the target machine. We use the
431 address size field from the CU header. */
432 if (cu->address_size == 4)
433 address = read_4ubyte_unaligned_inc (dbg, linep);
434 else
435 address = read_8ubyte_unaligned_inc (dbg, linep);
436 break;
437
438 case DW_LNE_define_file:
439 {
440 char *fname = (char *) linep;
441 uint8_t *endp = memchr (linep, '\0', lineendp - linep);
442 if (endp == NULL)
443 goto invalid_data;
444 size_t fnamelen = endp - linep;
445 linep = endp + 1;
446
447 unsigned int diridx;
448 get_uleb128 (diridx, linep);
449 Dwarf_Word mtime;
450 get_uleb128 (mtime, linep);
451 Dwarf_Word filelength;
452 get_uleb128 (filelength, linep);
453
454 struct filelist *new_file =
455 (struct filelist *) alloca (sizeof (*new_file));
456 if (fname[0] == '/')
457 new_file->info.name = fname;
458 else
459 {
460 new_file->info.name =
461 libdw_alloc (dbg, char, 1, (dirarray[diridx]->len + 1
462 + fnamelen + 1));
463 char *cp = new_file->info.name;
464
465 if (dirarray[diridx]->dir != NULL)
466 /* This value could be NULL in case the
467 DW_AT_comp_dir was not present. We
468 cannot do much in this case. The easiest
469 thing is to convert the path in an
470 absolute path. */
471 cp = stpcpy (cp, dirarray[diridx]->dir);
472 *cp++ = '/';
473 strcpy (cp, fname);
474 }
475
476 new_file->info.mtime = mtime;
477 new_file->info.length = filelength;
478 new_file->next = filelist;
479 filelist = new_file;
480 ++nfilelist;
481 }
482 break;
483
484 default:
485 /* Unknown, ignore it. */
486 linep += len - 1;
487 break;
488 }
489 }
Ben Chengcc6695e2012-03-07 23:04:02 -0800490 else if (opcode <= DW_LNS_set_epilogue_begin)
The Android Open Source Project441f72d2009-03-03 19:29:28 -0800491 {
492 /* This is a known standard opcode. */
493 switch (opcode)
494 {
495 case DW_LNS_copy:
496 /* Takes no argument. */
497 if (unlikely (standard_opcode_lengths[opcode] != 0))
498 goto invalid_data;
499
500 /* Add a new line with the current state machine values. */
501 NEW_LINE (0);
502
503 /* Reset the flags. */
504 basic_block = 0;
505 /* XXX Whether the following two lines are necessary is
506 unclear. I guess the current v2.1 specification has
507 a bug in that it says clearing these two registers is
508 not necessary. */
509 prologue_end = 0;
510 epilogue_begin = 0;
511 break;
512
513 case DW_LNS_advance_pc:
514 /* Takes one uleb128 parameter which is added to the
515 address. */
516 if (unlikely (standard_opcode_lengths[opcode] != 1))
517 goto invalid_data;
518
519 get_uleb128 (u128, linep);
520 address += minimum_instr_len * u128;
521 break;
522
523 case DW_LNS_advance_line:
524 /* Takes one sleb128 parameter which is added to the
525 line. */
526 if (unlikely (standard_opcode_lengths[opcode] != 1))
527 goto invalid_data;
528
529 get_sleb128 (s128, linep);
530 line += s128;
531 break;
532
533 case DW_LNS_set_file:
534 /* Takes one uleb128 parameter which is stored in file. */
535 if (unlikely (standard_opcode_lengths[opcode] != 1))
536 goto invalid_data;
537
538 get_uleb128 (u128, linep);
539 file = u128;
540 break;
541
542 case DW_LNS_set_column:
543 /* Takes one uleb128 parameter which is stored in column. */
544 if (unlikely (standard_opcode_lengths[opcode] != 1))
545 goto invalid_data;
546
547 get_uleb128 (u128, linep);
548 column = u128;
549 break;
550
551 case DW_LNS_negate_stmt:
552 /* Takes no argument. */
553 if (unlikely (standard_opcode_lengths[opcode] != 0))
554 goto invalid_data;
555
556 is_stmt = 1 - is_stmt;
557 break;
558
559 case DW_LNS_set_basic_block:
560 /* Takes no argument. */
561 if (unlikely (standard_opcode_lengths[opcode] != 0))
562 goto invalid_data;
563
564 basic_block = 1;
565 break;
566
567 case DW_LNS_const_add_pc:
568 /* Takes no argument. */
569 if (unlikely (standard_opcode_lengths[opcode] != 0))
570 goto invalid_data;
571
572 address += (minimum_instr_len
573 * ((255 - opcode_base) / line_range));
574 break;
575
576 case DW_LNS_fixed_advance_pc:
577 /* Takes one 16 bit parameter which is added to the
578 address. */
579 if (unlikely (standard_opcode_lengths[opcode] != 1))
580 goto invalid_data;
581
582 address += read_2ubyte_unaligned_inc (dbg, linep);
583 break;
584
585 case DW_LNS_set_prologue_end:
586 /* Takes no argument. */
587 if (unlikely (standard_opcode_lengths[opcode] != 0))
588 goto invalid_data;
589
590 prologue_end = 1;
591 break;
592
Ben Chengcc6695e2012-03-07 23:04:02 -0800593 case DW_LNS_set_epilogue_begin:
The Android Open Source Project441f72d2009-03-03 19:29:28 -0800594 /* Takes no argument. */
595 if (unlikely (standard_opcode_lengths[opcode] != 0))
596 goto invalid_data;
597
598 epilogue_begin = 1;
599 break;
600 }
601 }
602 else
603 {
604 /* This is a new opcode the generator but not we know about.
605 Read the parameters associated with it but then discard
606 everything. Read all the parameters for this opcode. */
607 for (int n = standard_opcode_lengths[opcode]; n > 0; --n)
608 get_uleb128 (u128, linep);
609
610 /* Next round, ignore this opcode. */
611 continue;
612 }
613 }
614
615 /* Put all the files in an array. */
616 Dwarf_Files *files = libdw_alloc (dbg, Dwarf_Files,
617 sizeof (Dwarf_Files)
Ben Chengcc6695e2012-03-07 23:04:02 -0800618 + nfilelist * sizeof (Dwarf_Fileinfo)
619 + (ndirlist + 1) * sizeof (char *),
620 1);
621 const char **dirs = (void *) &files->info[nfilelist];
622
The Android Open Source Project441f72d2009-03-03 19:29:28 -0800623 files->nfiles = nfilelist;
624 while (nfilelist-- > 0)
625 {
626 files->info[nfilelist] = filelist->info;
627 filelist = filelist->next;
628 }
629 assert (filelist == NULL);
630
Ben Chengcc6695e2012-03-07 23:04:02 -0800631 /* Put all the directory strings in an array. */
632 files->ndirs = ndirlist;
633 for (unsigned int i = 0; i < ndirlist; ++i)
634 dirs[i] = dirarray[i]->dir;
635 dirs[ndirlist] = NULL;
636
The Android Open Source Project441f72d2009-03-03 19:29:28 -0800637 /* Remember the debugging descriptor. */
638 files->dbg = dbg;
639
640 /* Make the file data structure available through the CU. */
641 cu->files = files;
642
Ben Chengcc6695e2012-03-07 23:04:02 -0800643 void *buf = libdw_alloc (dbg, Dwarf_Lines, (sizeof (Dwarf_Lines)
The Android Open Source Project441f72d2009-03-03 19:29:28 -0800644 + (sizeof (Dwarf_Line)
645 * nlinelist)), 1);
Ben Chengcc6695e2012-03-07 23:04:02 -0800646
647 /* First use the buffer for the pointers, and sort the entries.
648 We'll write the pointers in the end of the buffer, and then
649 copy into the buffer from the beginning so the overlap works. */
650 assert (sizeof (Dwarf_Line) >= sizeof (Dwarf_Line *));
651 Dwarf_Line **sortlines = (buf + sizeof (Dwarf_Lines)
652 + ((sizeof (Dwarf_Line)
653 - sizeof (Dwarf_Line *)) * nlinelist));
654
655 /* The list is in LIFO order and usually they come in clumps with
656 ascending addresses. So fill from the back to probably start with
657 runs already in order before we sort. */
658 unsigned int i = nlinelist;
659 while (i-- > 0)
The Android Open Source Project441f72d2009-03-03 19:29:28 -0800660 {
Ben Chengcc6695e2012-03-07 23:04:02 -0800661 sortlines[i] = &linelist->line;
The Android Open Source Project441f72d2009-03-03 19:29:28 -0800662 linelist = linelist->next;
663 }
664 assert (linelist == NULL);
665
Ben Chengcc6695e2012-03-07 23:04:02 -0800666 /* Sort by ascending address. */
667 qsort (sortlines, nlinelist, sizeof sortlines[0], &compare_lines);
668
669 /* Now that they are sorted, put them in the final array.
670 The buffers overlap, so we've clobbered the early elements
671 of SORTLINES by the time we're reading the later ones. */
672 cu->lines = buf;
673 cu->lines->nlines = nlinelist;
674 for (i = 0; i < nlinelist; ++i)
675 {
676 cu->lines->info[i] = *sortlines[i];
677 cu->lines->info[i].files = files;
678 }
679
The Android Open Source Project441f72d2009-03-03 19:29:28 -0800680 /* Success. */
681 res = 0;
682 }
683 else if (cu->lines != (void *) -1l)
684 /* We already have the information. */
685 res = 0;
686
687 if (likely (res == 0))
688 {
689 *lines = cu->lines;
690 *nlines = cu->lines->nlines;
691 }
692 out:
693
694 // XXX Eventually: unlocking here.
695
696 return res;
697}
Ben Chengcc6695e2012-03-07 23:04:02 -0800698INTDEF(dwarf_getsrclines)