xref: /titanic_52/usr/src/lib/libdwarf/common/dwarf_sort_line.c (revision 7fd791373689a6af05e27efec3b1ab556e02aa23)
1 /*
2   Copyright (C) 2000,2002,2004,2006 Silicon Graphics, Inc.  All Rights Reserved.
3   Portions Copyright (C) 2007-2010 David Anderson. All Rights Reserved.
4 
5   This program is free software; you can redistribute it and/or modify it
6   under the terms of version 2.1 of the GNU Lesser General Public License
7   as published by the Free Software Foundation.
8 
9   This program is distributed in the hope that it would be useful, but
10   WITHOUT ANY WARRANTY; without even the implied warranty of
11   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 
13   Further, this software is distributed without any warranty that it is
14   free of the rightful claim of any third person regarding infringement
15   or the like.  Any license provided herein, whether implied or
16   otherwise, applies only to this software file.  Patent licenses, if
17   any, provided herein do not apply to combinations of this program with
18   other software, or any other product whatsoever.
19 
20   You should have received a copy of the GNU Lesser General Public
21   License along with this program; if not, write the Free Software
22   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
23   USA.
24 
25   Contact information:  Silicon Graphics, Inc., 1500 Crittenden Lane,
26   Mountain View, CA 94043, or:
27 
28   http://www.sgi.com
29 
30   For further information regarding this notice, see:
31 
32   http://oss.sgi.com/projects/GenInfo/NoticeExplan
33 
34 */
35 /* The address of the Free Software Foundation is
36    Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
37    Boston, MA 02110-1301, USA.
38    SGI has moved from the Crittenden Lane address.
39 */
40 
41 
42 /* This file was designed for SGI IRIX compiler use.
43    The static linker can rearrange the order of functions
44    in the layout in memory
45    and provided each has the right  form
46    this will (when called by the SGI IRIX
47    static linker) rearrange the table so the line table
48    is arranged in the same order as the memory layout. */
49 
50 
51 
52 #include "config.h"
53 #include "dwarf_incl.h"
54 #include <stdio.h>
55 #include <stdlib.h>
56 #include "dwarf_line.h"
57 #ifdef HAVE_ALLOCA_H
58 #include <alloca.h>
59 #endif
60 #ifdef HAVE_STRING_H
61 #include <string.h>
62 #endif
63 
64 #define MINIMUM_POSSIBLE_PROLOG_LEN 10  /* 10 is based on */
65         /* the definition of the DWARF2/3 line table prolog. The value
66            here should be >8 (accounting for a 64 bit read) and <= the
67            length of a legal DWARF2/3 line prolog, which is at least 10
68            bytes long (but can be longer). What this constant helps
69            avoid is reading past the end of a malloc'd buffer in
70            _dwarf_update_line_sec(). */
71 
72 static int
73   _dwarf_update_line_sec(Dwarf_Small * line_ptr,
74                          unsigned long remaining_bytes,
75                          int *any_change,
76                          int length_size,
77                          int *err_code, Dwarf_Small ** new_line_ptr);
78 
79 /* Used to construct
80    a linked list of so we can sort and reorder the line info.
81 */
82 struct a_line_area {
83     Dwarf_Addr ala_address;     /* from DW_LNE_set_address */
84     Dwarf_Unsigned ala_offset;  /* byte offset in buffer */
85     Dwarf_Unsigned ala_length;  /* byte length in buffer */
86     long ala_entry_num;         /* to guarantee stable sort */
87     struct a_line_area *ala_next;
88 };
89 
90 
91 /*
92         Written to support the SGI IRIX static linker.
93         It helps SGI IRIX ld
94         rearrange lines in .debug_line in a .o created with a text
95         section per function.   The SGI IRIX linker option is:
96                 -OPT:procedure_reorder=ON
97         where ld-cord (cord(1)ing by ld,
98         not by cord(1)) may have changed the function order.
99 
100         Returns
101         DW_DLV_OK if nothing went wrong.
102         DW_DLV_ERROR if could not do anything due to
103                 error.  the original buffer is unchanged.
104 
105         is_64_bit must be passed in by caller and tells
106         if this is a 32 or 64bit pointer object section
107         being processed.
108 
109         err_code must be a non-null pointer to integer.
110         If DW_DLV_ERROR is returned that integer is set
111         to a dwarf error code so the caller may
112         print it for diagnostic purposes.
113 
114         *any_change is set here
115                 set 0 if no sorting (movement) done.
116                 set 1 if some sorting (movement) done.
117         on all returns. On error return sets to 0.
118 
119         The _dwarf name form is now obsolete,
120         the dwarf_ name for is preferred.
121         Both names supported.
122 
123 */
124 int
125 _dwarf_ld_sort_lines(void *orig_buffer,
126                      unsigned long buffer_len,
127                      int is_64_bit, int *any_change, int *err_code)
128 {
129     return dwarf_ld_sort_lines(orig_buffer,buffer_len,
130         is_64_bit,any_change,err_code);
131 }
132 int
133 dwarf_ld_sort_lines(void *orig_buffer,
134                      unsigned long buffer_len,
135                      int is_64_bit, int *any_change, int *err_code)
136 {
137 
138     int length_size = 4;
139     Dwarf_Small *orig_line_ptr; /* our local copy of the user's input
140                                    buffer */
141     Dwarf_Small *line_ptr;      /* starts at orig_line_ptr, gets
142                                    incremented thru to end of our copy
143                                    of the input buffer */
144     Dwarf_Small *new_line_ptr;  /* output of _dwarf_update_line_sec(),
145                                    used to update line_ptr as we pass
146                                    thru compilation units in a .o
147                                    .debug_line */
148 
149     unsigned long remaining_bytes = buffer_len; /* total length of
150                                                    original area left
151                                                    to be processed.
152                                                    Changes as we pass
153                                                    thru compilation
154                                                    units in a .o
155                                                    .debug_line */
156 
157     int sec_res;
158     int lany_change = 0;
159     int did_change = 0;
160 
161     if (is_64_bit)
162         length_size = 8;
163 
164     *any_change = 0;
165     line_ptr = malloc(buffer_len);
166     if (!line_ptr) {
167         *err_code = DW_DLE_ALLOC_FAIL;
168         return DW_DLV_ERROR;
169     }
170     orig_line_ptr = line_ptr;
171     memcpy(line_ptr, orig_buffer, buffer_len);
172 
173 
174     /*
175        We must iterate thru each of a set of prologues and line data.
176        We process each set in turn. If all pass, we update the
177        passed-in buffer. */
178     sec_res = DW_DLV_OK;
179 
180     for (sec_res = _dwarf_update_line_sec(line_ptr,
181                                           remaining_bytes,
182                                           &lany_change,
183                                           length_size,
184                                           err_code,
185                                           &new_line_ptr);
186          (sec_res == DW_DLV_OK) && (remaining_bytes > 0);
187          sec_res = _dwarf_update_line_sec(line_ptr,
188                                           remaining_bytes,
189                                           &lany_change,
190                                           length_size,
191                                           err_code, &new_line_ptr)) {
192         long bytes_used = new_line_ptr - line_ptr;
193 
194         line_ptr = new_line_ptr;
195         remaining_bytes -= bytes_used;
196         if (lany_change) {
197             did_change = 1;
198         }
199         if (remaining_bytes > 0) {
200             continue;
201         }
202         break;
203     }
204     if (sec_res == DW_DLV_ERROR) {
205         free(orig_line_ptr);
206         return sec_res;
207     }
208 
209 
210     /* all passed */
211     if (did_change) {
212         /* So update the passed in buffer orig_buffer is caller's input
213            area. orig_line_ptr is our modified copy of input area. */
214         memcpy(orig_buffer, orig_line_ptr, buffer_len);
215         *any_change = 1;
216     }
217     free(orig_line_ptr);
218 
219     return sec_res;
220 }
221 
222 
223 /* By setting ala_entry_num we guarantee a stable sort,
224         no duplicates
225    Sorting in address order.
226 */
227 static int
228 cmpr(const void *lin, const void *rin)
229 {
230     const struct a_line_area *l = lin;
231     const struct a_line_area *r = rin;
232 
233     if (l->ala_address < r->ala_address) {
234         return -1;
235     }
236     if (l->ala_address > r->ala_address) {
237         return 1;
238     }
239     if (l->ala_entry_num < r->ala_entry_num) {
240         return -1;
241     }
242     if (l->ala_entry_num > r->ala_entry_num) {
243         return 1;
244     }
245     return 0;                   /* should never happen. */
246 }
247 
248 /* The list of line area records is no longer needed.
249    Free the data allocated. */
250 static void
251 free_area_data(struct a_line_area *arp)
252 {
253     while(arp) {
254         struct a_line_area *next = arp->ala_next;
255         free(arp);
256         arp = next;
257     }
258 }
259 
260 /*
261         On entry:
262           line_ptr must point to first
263           byte of a line group for one (original) .o
264 
265           remaining_bytes is the size of the area pointed to
266           by line_ptr: may be larger than the
267           current original compilation unit .
268 
269           length size is 4 for 32bit pointers, 8 for 64bit pointers
270           in the data pointed to.
271 
272 
273         On return:
274           return DW_DLV_OK if all ok.  (ignore
275                 *err_code in this case)
276 
277           return DW_DLV_ERROR and set *err_code if an error.
278 
279           If some line data was moved around, set *any_change to 1.
280           If error or no movement, set *any_change to 0;
281 
282           Set *new_line_ptr to one-byte-past the end of the
283           current original compilation unit  (not necessary
284           if returning DW_DLV_ERROR, but not harmful).
285 
286 
287         This copies the entire array to a malloc area, then
288         mallocs pieces of it (another malloc) for sorting a CU entries
289         and copying back.  Then at end  the whole new thing copied in.
290         The result is that on error, the input is not touched.
291 
292         An alternative would be to just update a piece at a time
293         and on error stop updating but leave what was done, done.
294         This alternative would save some temporary malloc space.
295 
296 
297 */
298 static int
299 _dwarf_update_line_sec(Dwarf_Small * line_ptr,
300                        unsigned long remaining_bytes,
301                        int *any_change,
302                        int length_size,
303                        int *err_code, Dwarf_Small ** new_line_ptr)
304 {
305 
306 
307     /*
308        This points to the last byte of the .debug_line portion for the
309        current cu. */
310     Dwarf_Small *line_ptr_end = 0;
311 
312     /*
313        This points to the end of the statement program prologue for the
314        current cu, and serves to check that the prologue was correctly
315        decoded. */
316 
317     Dwarf_Small *orig_line_ptr = 0;
318 
319     /* These are the fields of the statement program header. */
320     struct Dwarf_Debug_s dbg_data;
321     Dwarf_Debug dbg = &dbg_data;
322 
323     /* These are the state machine state variables. */
324     Dwarf_Addr address = 0;
325     Dwarf_Word line = 1;
326     Dwarf_Bool is_stmt = false;
327 
328     /* Dwarf_Bool prologue_end; Dwarf_Bool epilogue_begin; */
329     Dwarf_Small isa = 0;
330 
331 
332     struct a_line_area *area_base = 0;
333     struct a_line_area *area_current = 0;
334     long area_count = 0;
335 
336     Dwarf_Addr last_address = 0;
337     int need_to_sort = 0;
338 
339     /*
340        This is the current opcode read from the statement program. */
341     Dwarf_Small opcode = 0;
342 
343 
344     /*
345        These variables are used to decode leb128 numbers. Leb128_num
346        holds the decoded number, and leb128_length is its length in
347        bytes. */
348     Dwarf_Word leb128_num = 0;
349     Dwarf_Sword advance_line = 0;
350 
351     /*
352        This is the operand of the latest fixed_advance_pc extended
353        opcode. */
354     Dwarf_Half fixed_advance_pc = 0;
355 
356     /* This is the length of an extended opcode instr.  */
357     Dwarf_Word instr_length = 0;
358     Dwarf_Small ext_opcode = 0;
359     struct Line_Table_Prefix_s prefix;
360 
361 
362 
363     memset(dbg, 0, sizeof(struct Dwarf_Debug_s));
364     dbg->de_copy_word = memcpy;
365     /*
366        Following is a straightforward decoding of the statement program
367        prologue information. */
368     *any_change = 0;
369 
370 
371     orig_line_ptr = line_ptr;
372     if (remaining_bytes < MINIMUM_POSSIBLE_PROLOG_LEN) {
373         /* We are at the end. Remaining should be zero bytes, padding.
374            This is really just 'end of CU buffer' not an error. The is
375            no 'entry' left so report there is none. We don't want to
376            READ_UNALIGNED the total_length below and then belatedly
377            discover that we read off the end already. */
378         return (DW_DLV_NO_ENTRY);
379     }
380 
381     dwarf_init_line_table_prefix(&prefix);
382     {
383         Dwarf_Small *line_ptr_out = 0;
384         Dwarf_Error error;
385         int dres = dwarf_read_line_table_prefix(dbg,
386             line_ptr,
387             remaining_bytes,
388             &line_ptr_out,
389             &prefix,
390             NULL, NULL,&error,
391             NULL);
392 
393         if (dres == DW_DLV_ERROR) {
394             dwarf_free_line_table_prefix(&prefix);
395             *err_code = dwarf_errno(error);
396             dwarf_dealloc(dbg, error, DW_DLA_ERROR);
397             free_area_data(area_base);
398             return dres;
399         }
400         if (dres == DW_DLV_NO_ENTRY) {
401             dwarf_free_line_table_prefix(&prefix);
402             return dres;
403         }
404         line_ptr_end = prefix.pf_line_ptr_end;
405 
406         line_ptr = line_ptr_out;
407     }
408 
409 
410     /* Initialize the state machine.  */
411     /* file = 1; */
412     /* column = 0; */
413     is_stmt = prefix.pf_default_is_stmt;
414     /* basic_block = false; */
415     /* end_sequence = false; */
416     /* prologue_end = false; */
417     /* epilogue_begin = false; */
418     isa = 0;
419 
420 
421     /* Start of statement program.  */
422     while (line_ptr < line_ptr_end) {
423         int type;
424 
425         Dwarf_Small *stmt_prog_entry_start = line_ptr;
426 
427         opcode = *(Dwarf_Small *) line_ptr;
428         line_ptr++;
429         /* 'type' is the output */
430         WHAT_IS_OPCODE(type, opcode, prefix.pf_opcode_base,
431                        prefix.pf_opcode_length_table, line_ptr,
432                        prefix.pf_std_op_count);
433 
434         if (type == LOP_DISCARD) {
435             int oc;
436             int opcnt = prefix.pf_opcode_length_table[opcode];
437 
438             for (oc = 0; oc < opcnt; oc++) {
439                 /*
440                  ** Read and discard operands we don't
441                  ** understand.
442                  ** arbitrary choice of unsigned read.
443                  ** signed read would work as well.
444                  */
445                 Dwarf_Unsigned utmp2;
446 
447                 DECODE_LEB128_UWORD(line_ptr, utmp2);
448             }
449 
450         } else if (type == LOP_SPECIAL) {
451             opcode = opcode - prefix.pf_opcode_base;
452             address = address + prefix.pf_minimum_instruction_length *
453                 (opcode / prefix.pf_line_range);
454             line =
455                 line + prefix.pf_line_base +
456                 opcode % prefix.pf_line_range;
457 
458             /* basic_block = false; */
459 
460 
461         } else if (type == LOP_STANDARD) {
462 
463 
464             switch (opcode) {
465 
466 
467             case DW_LNS_copy:{
468 
469                     /* basic_block = false; */
470                     break;
471                 }
472 
473             case DW_LNS_advance_pc:{
474                     Dwarf_Unsigned utmp2;
475 
476 
477                     DECODE_LEB128_UWORD(line_ptr, utmp2);
478                     leb128_num = (Dwarf_Word) utmp2;
479                     address =
480                         address +
481                         prefix.pf_minimum_instruction_length *
482                         leb128_num;
483                     break;
484                 }
485 
486             case DW_LNS_advance_line:{
487                     Dwarf_Signed stmp;
488 
489 
490                     DECODE_LEB128_SWORD(line_ptr, stmp);
491                     advance_line = (Dwarf_Sword) stmp;
492                     line = line + advance_line;
493                     break;
494                 }
495 
496             case DW_LNS_set_file:{
497                     Dwarf_Unsigned utmp2;
498 
499 
500                     DECODE_LEB128_UWORD(line_ptr, utmp2);
501                     /* file = (Dwarf_Word)utmp2; */
502                     break;
503                 }
504 
505             case DW_LNS_set_column:{
506                     Dwarf_Unsigned utmp2;
507 
508 
509                     DECODE_LEB128_UWORD(line_ptr, utmp2);
510                     /* column = (Dwarf_Word)utmp2; */
511                     break;
512                 }
513 
514             case DW_LNS_negate_stmt:{
515 
516                     is_stmt = !is_stmt;
517                     break;
518                 }
519 
520             case DW_LNS_set_basic_block:{
521 
522                     /* basic_block = true; */
523                     break;
524                 }
525 
526             case DW_LNS_const_add_pc:{
527                     opcode = MAX_LINE_OP_CODE - prefix.pf_opcode_base;
528                     address =
529                         address +
530                         prefix.pf_minimum_instruction_length * (opcode /
531                                                                 prefix.
532                                                                 pf_line_range);
533 
534                     break;
535                 }
536 
537             case DW_LNS_fixed_advance_pc:{
538 
539                     READ_UNALIGNED(dbg, fixed_advance_pc, Dwarf_Half,
540                                    line_ptr, sizeof(Dwarf_Half));
541                     line_ptr += sizeof(Dwarf_Half);
542                     address = address + fixed_advance_pc;
543                     break;
544                 }
545                 /* New in DWARF3 */
546             case DW_LNS_set_prologue_end:{
547 
548                     /* prologue_end = true; */
549                     break;
550 
551 
552                 }
553                 /* New in DWARF3 */
554             case DW_LNS_set_epilogue_begin:{
555                     /* epilogue_begin = true; */
556                     break;
557                 }
558 
559                 /* New in DWARF3 */
560             case DW_LNS_set_isa:{
561                     Dwarf_Unsigned utmp2;
562 
563                     DECODE_LEB128_UWORD(line_ptr, utmp2);
564                     isa = utmp2;
565                     if (isa != utmp2) {
566                         /* The value of the isa did not fit in our
567                            local so we record it wrong. declare an
568                            error. */
569                         dwarf_free_line_table_prefix(&prefix);
570                         *err_code = DW_DLE_LINE_NUM_OPERANDS_BAD;
571                         free_area_data(area_base);
572                         return (DW_DLV_ERROR);
573                     }
574                     break;
575                 }
576 
577             }
578         } else if (type == LOP_EXTENDED) {
579 
580             Dwarf_Unsigned utmp3;
581 
582             DECODE_LEB128_UWORD(line_ptr, utmp3);
583             instr_length = (Dwarf_Word) utmp3;
584             ext_opcode = *(Dwarf_Small *) line_ptr;
585             line_ptr++;
586             switch (ext_opcode) {
587 
588             case DW_LNE_end_sequence:{
589                     /* end_sequence = true; */
590 
591                     address = 0;
592                     /* file = 1; */
593                     line = 1;
594                     /* column = 0; */
595                     is_stmt = prefix.pf_default_is_stmt;
596                     /* basic_block = false; */
597                     /* end_sequence = false; */
598                     /* prologue_end = false; */
599                     /* epilogue_begin = false; */
600                     break;
601                 }
602 
603             case DW_LNE_set_address:{
604                     {
605                         struct a_line_area *area;
606 
607                         READ_UNALIGNED(dbg, address, Dwarf_Addr,
608                                        line_ptr, length_size);
609                         /* Here we need to remember the offset into the
610                            buffer and check to see if address went
611                            down. */
612                         if (address < last_address) {
613                             need_to_sort = 1;
614                         }
615                         last_address = address;
616 
617                         area = malloc(sizeof(struct a_line_area));
618                         area->ala_address = address;
619                         area->ala_offset = stmt_prog_entry_start -
620                             orig_line_ptr;
621                         area->ala_entry_num = area_count;
622                         area->ala_next = 0;
623                         area->ala_length = 0;
624                         if (area_current) {
625                             area_current->ala_next = area;
626                             area_current->ala_length =
627                                 area->ala_offset -
628                                 area_current->ala_offset;
629                         }
630                         ++area_count;
631                         area_current = area;
632                         if (area_base == 0) {
633                             area_base = area;
634                         }
635 
636                         line_ptr += length_size;
637                     }
638                     break;
639                 }
640 
641             case DW_LNE_define_file:{
642                     break;
643                 }
644 
645             default:{
646                  Dwarf_Unsigned remaining_bytes = instr_length -1;
647                  line_ptr += remaining_bytes;
648                  break;
649                 }
650             }
651 
652         }
653     }
654 
655 
656     *new_line_ptr = line_ptr;
657     if (!need_to_sort) {
658         dwarf_free_line_table_prefix(&prefix);
659         free_area_data(area_base);
660         return (DW_DLV_OK);
661     }
662 
663     /* So now we have something to sort. First, finish off the last
664        area record: */
665     area_current->ala_length = (line_ptr - orig_line_ptr)
666         -area_current->ala_offset;
667 
668     /* Build and sort a simple array of sections. Forcing a stable sort
669        by comparing on sequence number. We will use the sorted list to
670        move sections of this part of the line table. Each 'section'
671        starting with a DW_LNE_set_address opcode, on the assumption
672        that such only get out of order where there was an ld-cord
673        function rearrangement and that it is meaningful to restart the
674        line info there. */
675     {
676         struct a_line_area *ala_array;
677         struct a_line_area *local;
678         long start_len;
679         Dwarf_Small *new_area;
680         long i;
681 
682         ala_array = malloc(area_count * sizeof(struct a_line_area));
683         if (!ala_array) {
684             dwarf_free_line_table_prefix(&prefix);
685             *err_code = DW_DLE_ALLOC_FAIL;
686             free_area_data(area_base);
687             return DW_DLV_ERROR;
688         }
689 
690         for (local = area_base, i = 0; local;
691              local = local->ala_next, ++i) {
692 
693             ala_array[i] = *local;
694         }
695         free_area_data(area_base);
696         /* Zero the stale pointers so we don't use them accidentally. */
697         area_base = 0;
698         area_current = 0;
699 
700         qsort(ala_array, area_count, sizeof(struct a_line_area), cmpr);
701 
702         /* Now we must rearrange the pieces of the line table. */
703 
704         start_len =
705             (prefix.pf_line_prologue_start +
706              prefix.pf_prologue_length) - orig_line_ptr;
707         new_area = malloc(remaining_bytes);
708         if (!new_area) {
709             free(ala_array);
710             *err_code = DW_DLE_ALLOC_FAIL;
711             dwarf_free_line_table_prefix(&prefix);
712             return DW_DLV_ERROR;
713         }
714         memcpy(new_area, orig_line_ptr, start_len);
715         line_ptr = new_area + start_len;
716         for (i = 0; i < area_count; ++i) {
717             memcpy(line_ptr, orig_line_ptr +
718                    ala_array[i].ala_offset, ala_array[i].ala_length);
719             line_ptr += ala_array[i].ala_length;
720         }
721 
722         memcpy(orig_line_ptr, new_area, remaining_bytes);
723 
724         free(new_area);
725         free(ala_array);
726         ala_array = 0;
727         new_area = 0;
728     }
729 
730     *any_change = 1;
731     dwarf_free_line_table_prefix(&prefix);
732     return (DW_DLV_OK);
733 }
734