Bug Summary

File:tools/debugedit.c
Warning:line 2690, column 17
Value stored to 'sec_offset' during its initialization is never read

Annotated Source Code

1/* Copyright (C) 2001-2003, 2005, 2007, 2009-2011, 2016, 2017 Red Hat, Inc.
2 Written by Alexander Larsson <alexl@redhat.com>, 2002
3 Based on code by Jakub Jelinek <jakub@redhat.com>, 2001.
4 String/Line table rewriting by Mark Wielaard <mjw@redhat.com>, 2017.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software Foundation,
18 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
19
20#include "system.h"
21
22/* Needed for libelf */
23#define _FILE_OFFSET_BITS64 64
24
25#include <assert.h>
26#include <byteswap.h>
27#include <endian.h>
28#include <errno(*__errno_location ()).h>
29#include <error.h>
30#include <limits.h>
31#include <string.h>
32#include <stdlib.h>
33#include <stdint.h>
34#include <inttypes.h>
35#include <unistd.h>
36#include <sys/types.h>
37#include <sys/stat.h>
38#include <fcntl.h>
39#include <popt.h>
40
41#include <gelf.h>
42#include <dwarf.h>
43
44/* Unfortunately strtab manipulation functions were only officially added
45 to elfutils libdw in 0.167. Before that there were internal unsupported
46 ebl variants. While libebl.h isn't supported we'll try to use it anyway
47 if the elfutils we build against is too old. */
48#include <elfutils/version.h>
49#if _ELFUTILS_PREREQ (0, 167)(169 >= ((0) * 1000 + (167)))
50#include <elfutils/libdwelf.h>
51typedef Dwelf_Strent Strent;
52typedef Dwelf_Strtab Strtab;
53#define strtab_initdwelf_strtab_init dwelf_strtab_init
54#define strtab_add(X,Y)dwelf_strtab_add(X,Y) dwelf_strtab_add(X,Y)
55#define strtab_add_len(X,Y,Z)dwelf_strtab_add_len(X,Y,Z) dwelf_strtab_add_len(X,Y,Z)
56#define strtab_freedwelf_strtab_free dwelf_strtab_free
57#define strtab_finalizedwelf_strtab_finalize dwelf_strtab_finalize
58#define strent_offsetdwelf_strent_off dwelf_strent_off
59#else
60#include <elfutils/libebl.h>
61typedef struct Ebl_Strent Strent;
62typedef struct Ebl_Strtab Strtab;
63#define strtab_initdwelf_strtab_init ebl_strtabinit
64#define strtab_add(X,Y)dwelf_strtab_add(X,Y) ebl_strtabadd(X,Y,0)
65#define strtab_add_len(X,Y,Z)dwelf_strtab_add_len(X,Y,Z) ebl_strtabadd(X,Y,Z)
66#define strtab_freedwelf_strtab_free ebl_strtabfree
67#define strtab_finalizedwelf_strtab_finalize ebl_strtabfinalize
68#define strent_offsetdwelf_strent_off ebl_strtaboffset
69#endif
70
71#include <search.h>
72
73#include <rpm/rpmio.h>
74#include <rpm/rpmpgp.h>
75#include "tools/hashtab.h"
76
77#define DW_TAG_partial_unit0x3c 0x3c
78#define DW_FORM_sec_offset0x17 0x17
79#define DW_FORM_exprloc0x18 0x18
80#define DW_FORM_flag_present0x19 0x19
81#define DW_FORM_ref_sig80x20 0x20
82
83char *base_dir = NULL((void*)0);
84char *dest_dir = NULL((void*)0);
85char *list_file = NULL((void*)0);
86int list_file_fd = -1;
87int do_build_id = 0;
88int no_recompute_build_id = 0;
89char *build_id_seed = NULL((void*)0);
90
91/* We go over the debug sections in two phases. In phase zero we keep
92 track of any needed changes and collect strings, indexes and
93 sizes. In phase one we do the actual replacements updating the
94 strings, indexes and writing out new debug sections. The following
95 keep track of various changes that might be needed. */
96
97/* Whether we need to do any literal string (DW_FORM_string) replacements
98 in debug_info. */
99static bool_Bool need_string_replacement = false0;
100/* Whether we need to do any updates of the string indexes (DW_FORM_strp)
101 in debug_info for string indexes. */
102static bool_Bool need_strp_update = false0;
103/* If the debug_line changes size we will need to update the
104 DW_AT_stmt_list attributes indexes in the debug_info. */
105static bool_Bool need_stmt_update = false0;
106
107/* Storage for dynamically allocated strings to put into string
108 table. Keep together in memory blocks of 16K. */
109#define STRMEMSIZE(16 * 1024) (16 * 1024)
110struct strmemblock
111{
112 struct strmemblock *next;
113 char memory[0];
114};
115
116/* We keep track of each index in the original string table and the
117 associated entry in the new table so we don't insert identical
118 strings into the new string table. If constructed correctly the
119 original strtab shouldn't contain duplicate strings anyway. Any
120 actual identical strings could be deduplicated, but searching for
121 and comparing the indexes is much faster than comparing strings
122 (and we don't have to construct replacement strings). */
123struct stridxentry
124{
125 uint32_t idx; /* Original index in the string table. */
126 Strent *entry; /* Entry in the new table. */
127};
128
129/* Storage for new string table entries. Keep together in memory to
130 quickly search through them with tsearch. */
131#define STRIDXENTRIES((16 * 1024) / sizeof (struct stridxentry)) ((16 * 1024) / sizeof (struct stridxentry))
132struct strentblock
133{
134 struct strentblock *next;
135 struct stridxentry entry[0];
136};
137
138/* All data to keep track of the existing and new string table. */
139struct strings
140{
141 Strtab *str_tab; /* The new string table. */
142 char *str_buf; /* New Elf_Data d_buf. */
143 struct strmemblock *blocks; /* The first strmemblock. */
144 struct strmemblock *last_block; /* The currently used strmemblock. */
145 size_t stridx; /* Next free byte in last block. */
146 struct strentblock *entries; /* The first string index block. */
147 struct strentblock *last_entries; /* The currently used strentblock. */
148 size_t entryidx; /* Next free entry in the last block. */
149 void *strent_root; /* strent binary search tree root. */
150};
151
152struct line_table
153{
154 size_t old_idx; /* Original offset. */
155 size_t new_idx; /* Offset in new debug_line section. */
156 ssize_t size_diff; /* Difference in (header) size. */
157 bool_Bool replace_dirs; /* Whether to replace any dir paths. */
158 bool_Bool replace_files; /* Whether to replace any file paths. */
159
160 /* Header fields. */
161 uint32_t unit_length;
162 uint16_t version;
163 uint32_t header_length;
164 uint8_t min_instr_len;
165 uint8_t max_op_per_instr; /* Only if version >= 4 */
166 uint8_t default_is_stmt;
167 int8_t line_base;
168 uint8_t line_range;
169 uint8_t opcode_base;
170};
171
172struct debug_lines
173{
174 struct line_table *table; /* Malloc/Realloced. */
175 size_t size; /* Total number of line_tables.
176 Updated by get_line_table. */
177 size_t used; /* Used number of line_tables.
178 Updated by get_line_table. */
179 size_t debug_lines_len; /* Total size of new debug_line section.
180 updated by edit_dwarf2_line. */
181 char *line_buf; /* New Elf_Data d_buf. */
182};
183
184typedef struct
185{
186 Elf *elf;
187 GElf_Ehdr ehdr;
188 Elf_Scn **scn;
189 const char *filename;
190 int lastscn;
191 size_t phnum;
192 struct strings strings;
193 struct debug_lines lines;
194 GElf_Shdr shdr[0];
195} DSO;
196
197static void
198setup_lines (struct debug_lines *lines)
199{
200 lines->table = NULL((void*)0);
201 lines->size = 0;
202 lines->used = 0;
203 lines->debug_lines_len = 0;
204 lines->line_buf = NULL((void*)0);
205}
206
207static void
208destroy_lines (struct debug_lines *lines)
209{
210 free (lines->table);
211 free (lines->line_buf);
212}
213
214typedef struct
215{
216 unsigned char *ptr;
217 uint32_t addend;
218 int ndx;
219} REL;
220
221typedef struct
222{
223 Elf64_Addr r_offset;
224 int ndx;
225} LINE_REL;
226
227#define read_uleb128(ptr)({ unsigned int ret = 0; unsigned int c; int shift = 0; do { c
= *ptr++; ret |= (c & 0x7f) << shift; shift += 7; }
while (c & 0x80); if (shift >= 35) ret = (2147483647 *
2U +1U); ret; })
({ \
228 unsigned int ret = 0; \
229 unsigned int c; \
230 int shift = 0; \
231 do \
232 { \
233 c = *ptr++; \
234 ret |= (c & 0x7f) << shift; \
235 shift += 7; \
236 } while (c & 0x80); \
237 \
238 if (shift >= 35) \
239 ret = UINT_MAX(2147483647 *2U +1U); \
240 ret; \
241})
242
243#define write_uleb128(ptr,val)({ uint32_t valv = (val); do { unsigned char c = valv & 0x7f
; valv >>= 7; if (valv) c |= 0x80; *ptr++ = c; } while (
valv); })
({ \
244 uint32_t valv = (val); \
245 do \
246 { \
247 unsigned char c = valv & 0x7f; \
248 valv >>= 7; \
249 if (valv) \
250 c |= 0x80; \
251 *ptr++ = c; \
252 } \
253 while (valv); \
254})
255
256static uint16_t (*do_read_16) (unsigned char *ptr);
257static uint32_t (*do_read_32) (unsigned char *ptr);
258static void (*do_write_16) (unsigned char *ptr, uint16_t val);
259static void (*do_write_32) (unsigned char *ptr, uint32_t val);
260
261static int ptr_size;
262static int cu_version;
263
264static inline uint16_t
265buf_read_ule16 (unsigned char *data)
266{
267 return data[0] | (data[1] << 8);
268}
269
270static inline uint16_t
271buf_read_ube16 (unsigned char *data)
272{
273 return data[1] | (data[0] << 8);
274}
275
276static inline uint32_t
277buf_read_ule32 (unsigned char *data)
278{
279 return data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
280}
281
282static inline uint32_t
283buf_read_ube32 (unsigned char *data)
284{
285 return data[3] | (data[2] << 8) | (data[1] << 16) | (data[0] << 24);
286}
287
288static const char *
289strptr (DSO *dso, int sec, off_t offset)
290{
291 Elf_Scn *scn;
292 Elf_Data *data;
293
294 scn = dso->scn[sec];
295 if (offset >= 0 && (GElf_Addr) offset < dso->shdr[sec].sh_size)
296 {
297 data = NULL((void*)0);
298 while ((data = elf_getdata (scn, data)) != NULL((void*)0))
299 {
300 if (data->d_buf
301 && offset >= data->d_off
302 && offset < data->d_off + data->d_size)
303 return (const char *) data->d_buf + (offset - data->d_off);
304 }
305 }
306
307 return NULL((void*)0);
308}
309
310
311#define read_8(ptr)*ptr++ *ptr++
312
313#define read_16(ptr)({ uint16_t ret = do_read_16 (ptr); ptr += 2; ret; }) ({ \
314 uint16_t ret = do_read_16 (ptr); \
315 ptr += 2; \
316 ret; \
317})
318
319#define read_32(ptr)({ uint32_t ret = do_read_32 (ptr); ptr += 4; ret; }) ({ \
320 uint32_t ret = do_read_32 (ptr); \
321 ptr += 4; \
322 ret; \
323})
324
325REL *relptr, *relend;
326int reltype;
327
328#define do_read_32_relocated(ptr)({ uint32_t dret = do_read_32 (ptr); if (relptr) { while (relptr
< relend && relptr->ptr < ptr) ++relptr; if
(relptr < relend && relptr->ptr == ptr) { if (
reltype == 9) dret += relptr->addend; else dret = relptr->
addend; } } dret; })
({ \
329 uint32_t dret = do_read_32 (ptr); \
330 if (relptr) \
331 { \
332 while (relptr < relend && relptr->ptr < ptr) \
333 ++relptr; \
334 if (relptr < relend && relptr->ptr == ptr) \
335 { \
336 if (reltype == SHT_REL9) \
337 dret += relptr->addend; \
338 else \
339 dret = relptr->addend; \
340 } \
341 } \
342 dret; \
343})
344
345#define read_32_relocated(ptr)({ uint32_t ret = ({ uint32_t dret = do_read_32 (ptr); if (relptr
) { while (relptr < relend && relptr->ptr < ptr
) ++relptr; if (relptr < relend && relptr->ptr ==
ptr) { if (reltype == 9) dret += relptr->addend; else dret
= relptr->addend; } } dret; }); ptr += 4; ret; })
({ \
346 uint32_t ret = do_read_32_relocated (ptr)({ uint32_t dret = do_read_32 (ptr); if (relptr) { while (relptr
< relend && relptr->ptr < ptr) ++relptr; if
(relptr < relend && relptr->ptr == ptr) { if (
reltype == 9) dret += relptr->addend; else dret = relptr->
addend; } } dret; })
; \
347 ptr += 4; \
348 ret; \
349})
350
351static void
352dwarf2_write_le16 (unsigned char *p, uint16_t v)
353{
354 p[0] = v;
355 p[1] = v >> 8;
356}
357
358static void
359dwarf2_write_le32 (unsigned char *p, uint32_t v)
360{
361 p[0] = v;
362 p[1] = v >> 8;
363 p[2] = v >> 16;
364 p[3] = v >> 24;
365}
366
367static void
368dwarf2_write_be16 (unsigned char *p, uint16_t v)
369{
370 p[1] = v;
371 p[0] = v >> 8;
372}
373
374static void
375dwarf2_write_be32 (unsigned char *p, uint32_t v)
376{
377 p[3] = v;
378 p[2] = v >> 8;
379 p[1] = v >> 16;
380 p[0] = v >> 24;
381}
382
383#define write_8(ptr,val)({ *ptr++ = (val); }) ({ \
384 *ptr++ = (val); \
385})
386
387#define write_16(ptr,val)({ do_write_16 (ptr,val); ptr += 2; }) ({ \
388 do_write_16 (ptr,val); \
389 ptr += 2; \
390})
391
392#define write_32(ptr,val)({ do_write_32 (ptr,val); ptr += 4; }) ({ \
393 do_write_32 (ptr,val); \
394 ptr += 4; \
395})
396
397/* relocated writes can only be called immediately after
398 do_read_32_relocated. ptr must be equal to relptr->ptr (or
399 relend). Might just update the addend. So relocations need to be
400 updated at the end. */
401
402#define do_write_32_relocated(ptr,val)({ if (relptr && relptr < relend && relptr
->ptr == ptr) { if (reltype == 9) do_write_32 (ptr, val - relptr
->addend); else relptr->addend = val; } else do_write_32
(ptr,val); })
({ \
403 if (relptr && relptr < relend && relptr->ptr == ptr) \
404 { \
405 if (reltype == SHT_REL9) \
406 do_write_32 (ptr, val - relptr->addend); \
407 else \
408 relptr->addend = val; \
409 } \
410 else \
411 do_write_32 (ptr,val); \
412})
413
414#define write_32_relocated(ptr,val)({ ({ if (relptr && relptr < relend && relptr
->ptr == ptr) { if (reltype == 9) do_write_32 (ptr, val - relptr
->addend); else relptr->addend = val; } else do_write_32
(ptr,val); }); ptr += 4; })
({ \
415 do_write_32_relocated (ptr,val)({ if (relptr && relptr < relend && relptr
->ptr == ptr) { if (reltype == 9) do_write_32 (ptr, val - relptr
->addend); else relptr->addend = val; } else do_write_32
(ptr,val); })
; \
416 ptr += 4; \
417})
418
419static struct
420 {
421 const char *name;
422 unsigned char *data;
423 Elf_Data *elf_data;
424 size_t size;
425 int sec, relsec;
426 } debug_sections[] =
427 {
428#define DEBUG_INFO0 0
429#define DEBUG_ABBREV1 1
430#define DEBUG_LINE2 2
431#define DEBUG_ARANGES3 3
432#define DEBUG_PUBNAMES4 4
433#define DEBUG_PUBTYPES5 5
434#define DEBUG_MACINFO6 6
435#define DEBUG_LOC7 7
436#define DEBUG_STR8 8
437#define DEBUG_FRAME9 9
438#define DEBUG_RANGES10 10
439#define DEBUG_TYPES11 11
440#define DEBUG_MACRO12 12
441#define DEBUG_GDB_SCRIPT13 13
442 { ".debug_info", NULL((void*)0), NULL((void*)0), 0, 0, 0 },
443 { ".debug_abbrev", NULL((void*)0), NULL((void*)0), 0, 0, 0 },
444 { ".debug_line", NULL((void*)0), NULL((void*)0), 0, 0, 0 },
445 { ".debug_aranges", NULL((void*)0), NULL((void*)0), 0, 0, 0 },
446 { ".debug_pubnames", NULL((void*)0), NULL((void*)0), 0, 0, 0 },
447 { ".debug_pubtypes", NULL((void*)0), NULL((void*)0), 0, 0, 0 },
448 { ".debug_macinfo", NULL((void*)0), NULL((void*)0), 0, 0, 0 },
449 { ".debug_loc", NULL((void*)0), NULL((void*)0), 0, 0, 0 },
450 { ".debug_str", NULL((void*)0), NULL((void*)0), 0, 0, 0 },
451 { ".debug_frame", NULL((void*)0), NULL((void*)0), 0, 0, 0 },
452 { ".debug_ranges", NULL((void*)0), NULL((void*)0), 0, 0, 0 },
453 { ".debug_types", NULL((void*)0), NULL((void*)0), 0, 0, 0 },
454 { ".debug_macro", NULL((void*)0), NULL((void*)0), 0, 0, 0 },
455 { ".debug_gdb_scripts", NULL((void*)0), NULL((void*)0), 0, 0, 0 },
456 { NULL((void*)0), NULL((void*)0), NULL((void*)0), 0, 0, 0 }
457 };
458
459struct abbrev_attr
460 {
461 unsigned int attr;
462 unsigned int form;
463 };
464
465struct abbrev_tag
466 {
467 unsigned int entry;
468 unsigned int tag;
469 int nattr;
470 struct abbrev_attr attr[0];
471 };
472
473static hashval_t
474abbrev_hash (const void *p)
475{
476 struct abbrev_tag *t = (struct abbrev_tag *)p;
477
478 return t->entry;
479}
480
481static int
482abbrev_eq (const void *p, const void *q)
483{
484 struct abbrev_tag *t1 = (struct abbrev_tag *)p;
485 struct abbrev_tag *t2 = (struct abbrev_tag *)q;
486
487 return t1->entry == t2->entry;
488}
489
490static void
491abbrev_del (void *p)
492{
493 free (p);
494}
495
496static htab_t
497read_abbrev (DSO *dso, unsigned char *ptr)
498{
499 htab_t h = htab_try_create (50, abbrev_hash, abbrev_eq, abbrev_del);
500 unsigned int attr, form;
501 struct abbrev_tag *t;
502 int size;
503 void **slot;
504
505 if (h == NULL((void*)0))
506 {
507no_memory:
508 error (0, ENOMEM12, "%s: Could not read .debug_abbrev", dso->filename);
509 if (h)
510 htab_delete (h);
511 return NULL((void*)0);
512 }
513
514 while ((attr = read_uleb128 (ptr)({ unsigned int ret = 0; unsigned int c; int shift = 0; do { c
= *ptr++; ret |= (c & 0x7f) << shift; shift += 7; }
while (c & 0x80); if (shift >= 35) ret = (2147483647 *
2U +1U); ret; })
) != 0)
515 {
516 size = 10;
517 t = malloc (sizeof (*t) + size * sizeof (struct abbrev_attr));
518 if (t == NULL((void*)0))
519 goto no_memory;
520 t->entry = attr;
521 t->nattr = 0;
522 slot = htab_find_slot (h, t, INSERT);
523 if (slot == NULL((void*)0))
524 {
525 free (t);
526 goto no_memory;
527 }
528 if (*slot != NULL((void*)0))
529 {
530 error (0, 0, "%s: Duplicate DWARF abbreviation %d", dso->filename,
531 t->entry);
532 free (t);
533 htab_delete (h);
534 return NULL((void*)0);
535 }
536 t->tag = read_uleb128 (ptr)({ unsigned int ret = 0; unsigned int c; int shift = 0; do { c
= *ptr++; ret |= (c & 0x7f) << shift; shift += 7; }
while (c & 0x80); if (shift >= 35) ret = (2147483647 *
2U +1U); ret; })
;
537 ++ptr; /* skip children flag. */
538 while ((attr = read_uleb128 (ptr)({ unsigned int ret = 0; unsigned int c; int shift = 0; do { c
= *ptr++; ret |= (c & 0x7f) << shift; shift += 7; }
while (c & 0x80); if (shift >= 35) ret = (2147483647 *
2U +1U); ret; })
) != 0)
539 {
540 if (t->nattr == size)
541 {
542 size += 10;
543 t = realloc (t, sizeof (*t) + size * sizeof (struct abbrev_attr));
544 if (t == NULL((void*)0))
545 goto no_memory;
546 }
547 form = read_uleb128 (ptr)({ unsigned int ret = 0; unsigned int c; int shift = 0; do { c
= *ptr++; ret |= (c & 0x7f) << shift; shift += 7; }
while (c & 0x80); if (shift >= 35) ret = (2147483647 *
2U +1U); ret; })
;
548 if (form == 2
549 || (form > DW_FORM_flag_present0x19 && form != DW_FORM_ref_sig80x20))
550 {
551 error (0, 0, "%s: Unknown DWARF DW_FORM_%d", dso->filename, form);
552 htab_delete (h);
553 return NULL((void*)0);
554 }
555
556 t->attr[t->nattr].attr = attr;
557 t->attr[t->nattr++].form = form;
558 }
559 if (read_uleb128 (ptr)({ unsigned int ret = 0; unsigned int c; int shift = 0; do { c
= *ptr++; ret |= (c & 0x7f) << shift; shift += 7; }
while (c & 0x80); if (shift >= 35) ret = (2147483647 *
2U +1U); ret; })
!= 0)
560 {
561 error (0, 0, "%s: DWARF abbreviation does not end with 2 zeros",
562 dso->filename);
563 htab_delete (h);
564 return NULL((void*)0);
565 }
566 *slot = t;
567 }
568
569 return h;
570}
571
572#define IS_DIR_SEPARATOR(c)((c)=='/') ((c)=='/')
573
574static char *
575canonicalize_path (const char *s, char *d)
576{
577 char *rv = d;
578 char *droot;
579
580 if (IS_DIR_SEPARATOR (*s)((*s)=='/'))
581 {
582 *d++ = *s++;
583 if (IS_DIR_SEPARATOR (*s)((*s)=='/') && !IS_DIR_SEPARATOR (s[1])((s[1])=='/'))
584 {
585 /* Special case for "//foo" meaning a Posix namespace
586 escape. */
587 *d++ = *s++;
588 }
589 while (IS_DIR_SEPARATOR (*s)((*s)=='/'))
590 s++;
591 }
592 droot = d;
593
594 while (*s)
595 {
596 /* At this point, we're always at the beginning of a path
597 segment. */
598
599 if (s[0] == '.' && (s[1] == 0 || IS_DIR_SEPARATOR (s[1])((s[1])=='/')))
600 {
601 s++;
602 if (*s)
603 while (IS_DIR_SEPARATOR (*s)((*s)=='/'))
604 ++s;
605 }
606
607 else if (s[0] == '.' && s[1] == '.'
608 && (s[2] == 0 || IS_DIR_SEPARATOR (s[2])((s[2])=='/')))
609 {
610 char *pre = d - 1; /* includes slash */
611 while (droot < pre && IS_DIR_SEPARATOR (*pre)((*pre)=='/'))
612 pre--;
613 if (droot <= pre && ! IS_DIR_SEPARATOR (*pre)((*pre)=='/'))
614 {
615 while (droot < pre && ! IS_DIR_SEPARATOR (*pre)((*pre)=='/'))
616 pre--;
617 /* pre now points to the slash */
618 if (droot < pre)
619 pre++;
620 if (pre + 3 == d && pre[0] == '.' && pre[1] == '.')
621 {
622 *d++ = *s++;
623 *d++ = *s++;
624 }
625 else
626 {
627 d = pre;
628 s += 2;
629 if (*s)
630 while (IS_DIR_SEPARATOR (*s)((*s)=='/'))
631 s++;
632 }
633 }
634 else
635 {
636 *d++ = *s++;
637 *d++ = *s++;
638 }
639 }
640 else
641 {
642 while (*s && ! IS_DIR_SEPARATOR (*s)((*s)=='/'))
643 *d++ = *s++;
644 }
645
646 if (IS_DIR_SEPARATOR (*s)((*s)=='/'))
647 {
648 *d++ = *s++;
649 while (IS_DIR_SEPARATOR (*s)((*s)=='/'))
650 s++;
651 }
652 }
653 while (droot < d && IS_DIR_SEPARATOR (d[-1])((d[-1])=='/'))
654 --d;
655 if (d == rv)
656 *d++ = '.';
657 *d = 0;
658
659 return rv;
660}
661
662/* Returns the rest of PATH if it starts with DIR_PREFIX, skipping any
663 / path separators, or NULL if PATH doesn't start with
664 DIR_PREFIX. Might return the empty string if PATH equals DIR_PREFIX
665 (modulo trailing slashes). Never returns path starting with '/'.
666 Note that DIR_PREFIX itself should NOT end with a '/'. */
667static const char *
668skip_dir_prefix (const char *path, const char *dir_prefix)
669{
670 size_t prefix_len = strlen (dir_prefix);
671 if (strncmp (path, dir_prefix, prefix_len) == 0)
672 {
673 path += prefix_len;
674 /* Unless path == dir_prefix there should be at least one '/'
675 in the path (which we will skip). Otherwise the path has
676 a different (longer) directory prefix. */
677 if (*path != '\0' && !IS_DIR_SEPARATOR (*path)((*path)=='/'))
678 return NULL((void*)0);
679 while (IS_DIR_SEPARATOR (path[0])((path[0])=='/'))
680 path++;
681 return path;
682 }
683
684 return NULL((void*)0);
685}
686
687/* Most strings will be in the existing debug string table. But to
688 replace the base/dest directory prefix we need some new storage.
689 Keep new strings somewhat close together for faster comparison and
690 copying. SIZE should be at least one (and includes space for the
691 zero terminator). The returned pointer points to uninitialized
692 data. */
693static char *
694new_string_storage (struct strings *strings, size_t size)
695{
696 assert (size > 0)({ if (size > 0) ; else __assert_fail ("size > 0", "tools/debugedit.c"
, 696, __PRETTY_FUNCTION__); })
;
697
698 /* If the string is extra long just create a whole block for
699 it. Normally strings are much smaller than STRMEMSIZE. */
700 if (strings->last_block == NULL((void*)0)
701 || size > STRMEMSIZE(16 * 1024)
702 || strings->stridx > STRMEMSIZE(16 * 1024)
703 || (STRMEMSIZE(16 * 1024) - strings->stridx) < size)
704 {
705 struct strmemblock *newblock = malloc (sizeof (struct strmemblock)
706 + MAX (STRMEMSIZE, size)((((16 * 1024))>(size))?((16 * 1024)):(size)));
707 if (newblock == NULL((void*)0))
708 return NULL((void*)0);
709
710 newblock->next = NULL((void*)0);
711
712 if (strings->blocks == NULL((void*)0))
713 strings->blocks = newblock;
714
715 if (strings->last_block != NULL((void*)0))
716 strings->last_block->next = newblock;
717
718 strings->last_block = newblock;
719 strings->stridx = 0;
720 }
721
722 size_t stridx = strings->stridx;
723 strings->stridx += size + 1;
724 return &strings->last_block->memory[stridx];
725}
726
727/* Comparison function used for tsearch. */
728static int
729strent_compare (const void *a, const void *b)
730{
731 struct stridxentry *entry_a = (struct stridxentry *)a;
732 struct stridxentry *entry_b = (struct stridxentry *)b;
733 size_t idx_a = entry_a->idx;
734 size_t idx_b = entry_b->idx;
735
736 if (idx_a < idx_b)
737 return -1;
738
739 if (idx_a > idx_b)
740 return 1;
741
742 return 0;
743}
744
745/* Allocates and inserts a new entry for the old index if not yet
746 seen. Returns a stridxentry if the given index has not yet been
747 seen and needs to be filled in with the associated string (either
748 the original string or the replacement string). Returns NULL if the
749 idx is already known. Use in phase 0 to add all strings seen. In
750 phase 1 use string_find_entry instead to get existing entries. */
751static struct stridxentry *
752string_find_new_entry (struct strings *strings, size_t old_idx)
753{
754 /* Use next entry in the pool for lookup so we can use it directly
755 if this is a new index. */
756 struct stridxentry *entry;
757
758 /* Keep entries close together to make key comparison fast. */
759 if (strings->last_entries == NULL((void*)0) || strings->entryidx >= STRIDXENTRIES((16 * 1024) / sizeof (struct stridxentry)))
760 {
761 size_t entriessz = (sizeof (struct strentblock)
762 + (STRIDXENTRIES((16 * 1024) / sizeof (struct stridxentry)) * sizeof (struct stridxentry)));
763 struct strentblock *newentries = malloc (entriessz);
764 if (newentries == NULL((void*)0))
765 error (1, errno(*__errno_location ()), "Couldn't allocate new string entries block");
766 else
767 {
768 if (strings->entries == NULL((void*)0))
769 strings->entries = newentries;
770
771 if (strings->last_entries != NULL((void*)0))
772 strings->last_entries->next = newentries;
773
774 strings->last_entries = newentries;
775 strings->last_entries->next = NULL((void*)0);
776 strings->entryidx = 0;
777 }
778 }
779
780 entry = &strings->last_entries->entry[strings->entryidx];
781 entry->idx = old_idx;
782 struct stridxentry **tres = tsearch (entry, &strings->strent_root,
783 strent_compare);
784 if (tres == NULL((void*)0))
785 error (1, ENOMEM12, "Couldn't insert new strtab idx");
786 else if (*tres == entry)
787 {
788 /* idx not yet seen, must add actual str. */
789 strings->entryidx++;
790 return entry;
791 }
792
793 return NULL((void*)0); /* We already know about this idx, entry already complete. */
794}
795
796static struct stridxentry *
797string_find_entry (struct strings *strings, size_t old_idx)
798{
799 struct stridxentry **ret;
800 struct stridxentry key;
801 key.idx = old_idx;
802 ret = tfind (&key, &strings->strent_root, strent_compare);
803 assert (ret != NULL)({ if (ret != ((void*)0)) ; else __assert_fail ("ret != NULL"
, "tools/debugedit.c", 803, __PRETTY_FUNCTION__); })
; /* Can only happen for a bad/non-existing old_idx. */
804 return *ret;
805}
806
807/* Adds a string_idx_entry given an index into the old/existing string
808 table. Should be used in phase 0. Does nothing if the index was
809 already registered. Otherwise it checks the string associated with
810 the index. If the old string doesn't start with base_dir an entry
811 will be recorded for the index with the same string. Otherwise a
812 string will be recorded where the base_dir prefix will be replaced
813 by dest_dir. Returns true if this is a not yet seen index and there
814 a replacement file string has been recorded for it, otherwise
815 returns false. */
816static bool_Bool
817record_file_string_entry_idx (struct strings *strings, size_t old_idx)
818{
819 bool_Bool ret = false0;
820 struct stridxentry *entry = string_find_new_entry (strings, old_idx);
821 if (entry != NULL((void*)0))
822 {
823 Strent *strent;
824 const char *old_str = (char *)debug_sections[DEBUG_STR8].data + old_idx;
825 const char *file = skip_dir_prefix (old_str, base_dir);
826 if (file == NULL((void*)0))
827 {
828 /* Just record the existing string. */
829 strent = strtab_add_len (strings->str_tab, old_str,dwelf_strtab_add_len(strings->str_tab,old_str,strlen (old_str
) + 1)
830 strlen (old_str) + 1)dwelf_strtab_add_len(strings->str_tab,old_str,strlen (old_str
) + 1)
;
831 }
832 else
833 {
834 /* Create and record the altered file path. */
835 size_t dest_len = strlen (dest_dir);
836 size_t file_len = strlen (file);
837 size_t nsize = dest_len + 1; /* + '\0' */
838 if (file_len > 0)
839 nsize += 1 + file_len; /* + '/' */
840 char *nname = new_string_storage (strings, nsize);
841 if (nname == NULL((void*)0))
842 error (1, ENOMEM12, "Couldn't allocate new string storage");
843 memcpy (nname, dest_dir, dest_len);
844 if (file_len > 0)
845 {
846 nname[dest_len] = '/';
847 memcpy (nname + dest_len + 1, file, file_len + 1);
848 }
849 else
850 nname[dest_len] = '\0';
851
852 strent = strtab_add_len (strings->str_tab, nname, nsize)dwelf_strtab_add_len(strings->str_tab,nname,nsize);
853 ret = true1;
854 }
855 if (strent == NULL((void*)0))
856 error (1, ENOMEM12, "Could not create new string table entry");
857 else
858 entry->entry = strent;
859 }
860
861 return ret;
862}
863
864/* Same as record_new_string_file_string_entry_idx but doesn't replace
865 base_dir with dest_dir, just records the existing string associated
866 with the index. */
867static void
868record_existing_string_entry_idx (struct strings *strings, size_t old_idx)
869{
870 struct stridxentry *entry = string_find_new_entry (strings, old_idx);
871 if (entry != NULL((void*)0))
872 {
873 const char *str = (char *)debug_sections[DEBUG_STR8].data + old_idx;
874 Strent *strent = strtab_add_len (strings->str_tab,dwelf_strtab_add_len(strings->str_tab,str,strlen (str) + 1
)
875 str, strlen (str) + 1)dwelf_strtab_add_len(strings->str_tab,str,strlen (str) + 1
)
;
876 if (strent == NULL((void*)0))
877 error (1, ENOMEM12, "Could not create new string table entry");
878 else
879 entry->entry = strent;
880 }
881}
882
883static void
884setup_strings (struct strings *strings)
885{
886 strings->str_tab = strtab_initdwelf_strtab_init (false0);
887 strings->str_buf = NULL((void*)0);
888 strings->blocks = NULL((void*)0);
889 strings->last_block = NULL((void*)0);
890 strings->entries = NULL((void*)0);
891 strings->last_entries = NULL((void*)0);
892 strings->strent_root = NULL((void*)0);
893}
894
895/* Noop for tdestroy. */
896static void free_node (void *p __attribute__((__unused__))) { }
897
898static void
899destroy_strings (struct strings *strings)
900{
901 struct strmemblock *smb = strings->blocks;
902 while (smb != NULL((void*)0))
903 {
904 void *old = smb;
905 smb = smb->next;
906 free (old);
907 }
908
909 struct strentblock *emb = strings->entries;
910 while (emb != NULL((void*)0))
911 {
912 void *old = emb;
913 emb = emb->next;
914 free (old);
915 }
916
917 strtab_freedwelf_strtab_free (strings->str_tab);
918 tdestroy (strings->strent_root, &free_node);
919 free (strings->str_buf);
920}
921
922/* The minimum number of line tables we pre-allocate. */
923#define MIN_LINE_TABLES64 64
924
925/* Gets a line_table at offset. Returns true if not yet know and
926 successfully read, false otherwise. Sets *table to NULL and
927 outputs a warning if there was a problem reading the table at the
928 given offset. */
929static bool_Bool
930get_line_table (DSO *dso, size_t off, struct line_table **table)
931{
932 struct debug_lines *lines = &dso->lines;
933 /* Assume there aren't that many, just do a linear search. The
934 array is probably already sorted because the stmt_lists are
935 probably inserted in order. But we cannot rely on that (maybe we
936 should check that to make searching quicker if possible?). Once
937 we have all line tables for phase 1 (rewriting) we do explicitly
938 sort the array.*/
939 for (int i = 0; i < lines->used; i++)
940 if (lines->table[i].old_idx == off)
941 {
942 *table = &lines->table[i];
943 return false0;
944 }
945
946 if (lines->size == lines->used)
947 {
948 struct line_table *new_table = realloc (lines->table,
949 (sizeof (struct line_table)
950 * (lines->size
951 + MIN_LINE_TABLES64)));
952 if (new_table == NULL((void*)0))
953 {
954 error (0, ENOMEM12, "Couldn't add more debug_line tables");
955 *table = NULL((void*)0);
956 return false0;
957 }
958 lines->table = new_table;
959 lines->size += MIN_LINE_TABLES64;
960 }
961
962 struct line_table *t = &lines->table[lines->used];
963 *table = NULL((void*)0);
964
965 t->old_idx = off;
966 t->size_diff = 0;
967 t->replace_dirs = false0;
968 t->replace_files = false0;
969
970 unsigned char *ptr = debug_sections[DEBUG_LINE2].data;
971 unsigned char *endsec = ptr + debug_sections[DEBUG_LINE2].size;
972 if (ptr == NULL((void*)0))
973 {
974 error (0, 0, "%s: No .line_table section", dso->filename);
975 return false0;
976 }
977
978 if (off > debug_sections[DEBUG_LINE2].size)
979 {
980 error (0, 0, "%s: Invalid .line_table offset 0x%zx",
981 dso->filename, off);
982 return false0;
983 }
984 ptr += off;
985
986 /* unit_length */
987 unsigned char *endcu = ptr + 4;
988 t->unit_length = read_32 (ptr)({ uint32_t ret = do_read_32 (ptr); ptr += 4; ret; });
989 endcu += t->unit_length;
990 if (endcu == ptr + 0xffffffff)
991 {
992 error (0, 0, "%s: 64-bit DWARF not supported", dso->filename);
993 return false0;
994 }
995
996 if (endcu > endsec)
997 {
998 error (0, 0, "%s: .debug_line CU does not fit into section",
999 dso->filename);
1000 return false0;
1001 }
1002
1003 /* version */
1004 t->version = read_16 (ptr)({ uint16_t ret = do_read_16 (ptr); ptr += 2; ret; });
1005 if (t->version != 2 && t->version != 3 && t->version != 4)
1006 {
1007 error (0, 0, "%s: DWARF version %d unhandled", dso->filename,
1008 t->version);
1009 return false0;
1010 }
1011
1012 /* header_length */
1013 unsigned char *endprol = ptr + 4;
1014 t->header_length = read_32 (ptr)({ uint32_t ret = do_read_32 (ptr); ptr += 4; ret; });
1015 endprol += t->header_length;
1016 if (endprol > endcu)
1017 {
1018 error (0, 0, "%s: .debug_line CU prologue does not fit into CU",
1019 dso->filename);
1020 return false0;
1021 }
1022
1023 /* min instr len */
1024 t->min_instr_len = *ptr++;
1025
1026 /* max op per instr, if version >= 4 */
1027 if (t->version >= 4)
1028 t->max_op_per_instr = *ptr++;
1029
1030 /* default is stmt */
1031 t->default_is_stmt = *ptr++;
1032
1033 /* line base */
1034 t->line_base = (*(int8_t *)ptr++);
1035
1036 /* line range */
1037 t->line_range = *ptr++;
1038
1039 /* opcode base */
1040 t->opcode_base = *ptr++;
1041
1042 if (ptr + t->opcode_base - 1 >= endcu)
1043 {
1044 error (0, 0, "%s: .debug_line opcode table does not fit into CU",
1045 dso->filename);
1046 return false0;
1047 }
1048 lines->used++;
1049 *table = t;
1050 return true1;
1051}
1052
1053static int dirty_elf;
1054static void
1055dirty_section (unsigned int sec)
1056{
1057 elf_flagdata (debug_sections[sec].elf_data, ELF_C_SET, ELF_F_DIRTYELF_F_DIRTY);
1058 dirty_elf = 1;
1059}
1060
1061static int
1062line_table_cmp (const void *a, const void *b)
1063{
1064 struct line_table *ta = (struct line_table *) a;
1065 struct line_table *tb = (struct line_table *) b;
1066
1067 if (ta->old_idx < tb->old_idx)
1068 return -1;
1069
1070 if (ta->old_idx > tb->old_idx)
1071 return 1;
1072
1073 return 0;
1074}
1075
1076
1077/* Called after phase zero (which records all adjustments needed for
1078 the line tables referenced from debug_info) and before phase one
1079 starts (phase one will adjust the .debug_line section stmt
1080 references using the updated data structures). */
1081static void
1082edit_dwarf2_line (DSO *dso)
1083{
1084 Elf_Data *linedata = debug_sections[DEBUG_LINE2].elf_data;
1085 int linendx = debug_sections[DEBUG_LINE2].sec;
1086 Elf_Scn *linescn = dso->scn[linendx];
1087 unsigned char *old_buf = linedata->d_buf;
1088
1089 /* Out with the old. */
1090 linedata->d_size = 0;
1091
1092 /* In with the new. */
1093 linedata = elf_newdata (linescn);
1094
1095 dso->lines.line_buf = malloc (dso->lines.debug_lines_len);
1096 if (dso->lines.line_buf == NULL((void*)0))
1097 error (1, ENOMEM12, "No memory for new .debug_line table (0x%zx bytes)",
1098 dso->lines.debug_lines_len);
1099
1100 linedata->d_size = dso->lines.debug_lines_len;
1101 linedata->d_buf = dso->lines.line_buf;
1102 debug_sections[DEBUG_LINE2].size = linedata->d_size;
1103
1104 /* Make sure the line tables are sorted on the old index. */
1105 qsort (dso->lines.table, dso->lines.used, sizeof (struct line_table),
1106 line_table_cmp);
1107
1108 unsigned char *ptr = linedata->d_buf;
1109 for (int ldx = 0; ldx < dso->lines.used; ldx++)
1110 {
1111 struct line_table *t = &dso->lines.table[ldx];
1112 unsigned char *optr = old_buf + t->old_idx;
1113 t->new_idx = ptr - (unsigned char *) linedata->d_buf;
1114
1115 /* Just copy the whole table if nothing needs replacing. */
1116 if (! t->replace_dirs && ! t->replace_files)
1117 {
1118 assert (t->size_diff == 0)({ if (t->size_diff == 0) ; else __assert_fail ("t->size_diff == 0"
, "tools/debugedit.c", 1118, __PRETTY_FUNCTION__); })
;
1119 memcpy (ptr, optr, t->unit_length + 4);
1120 ptr += t->unit_length + 4;
1121 continue;
1122 }
1123
1124 /* Header fields. */
1125 write_32 (ptr, t->unit_length + t->size_diff)({ do_write_32 (ptr,t->unit_length + t->size_diff); ptr
+= 4; })
;
1126 write_16 (ptr, t->version)({ do_write_16 (ptr,t->version); ptr += 2; });
1127 write_32 (ptr, t->header_length + t->size_diff)({ do_write_32 (ptr,t->header_length + t->size_diff); ptr
+= 4; })
;
1128 write_8 (ptr, t->min_instr_len)({ *ptr++ = (t->min_instr_len); });
1129 if (t->version >= 4)
1130 write_8 (ptr, t->max_op_per_instr)({ *ptr++ = (t->max_op_per_instr); });
1131 write_8 (ptr, t->default_is_stmt)({ *ptr++ = (t->default_is_stmt); });
1132 write_8 (ptr, t->line_base)({ *ptr++ = (t->line_base); });
1133 write_8 (ptr, t->line_range)({ *ptr++ = (t->line_range); });
1134 write_8 (ptr, t->opcode_base)({ *ptr++ = (t->opcode_base); });
1135
1136 optr += (4 /* unit len */
1137 + 2 /* version */
1138 + 4 /* header len */
1139 + 1 /* min instr len */
1140 + (t->version >= 4) /* max op per instr, if version >= 4 */
1141 + 1 /* default is stmt */
1142 + 1 /* line base */
1143 + 1 /* line range */
1144 + 1); /* opcode base */
1145
1146 /* opcode len table. */
1147 memcpy (ptr, optr, t->opcode_base - 1);
1148 optr += t->opcode_base - 1;
1149 ptr += t->opcode_base - 1;
1150
1151 /* directory table. We need to find the end (start of file
1152 table) anyway, so loop over all dirs, even if replace_dirs is
1153 false. */
1154 while (*optr != 0)
1155 {
1156 const char *dir = (const char *) optr;
1157 const char *file_path = NULL((void*)0);
1158 if (t->replace_dirs)
1159 {
1160 file_path = skip_dir_prefix (dir, base_dir);
1161 if (file_path != NULL((void*)0))
1162 {
1163 size_t dest_len = strlen (dest_dir);
1164 size_t file_len = strlen (file_path);
1165 memcpy (ptr, dest_dir, dest_len);
1166 ptr += dest_len;
1167 if (file_len > 0)
1168 {
1169 *ptr++ = '/';
1170 memcpy (ptr, file_path, file_len);
1171 ptr += file_len;
1172 }
1173 *ptr++ = '\0';
1174 }
1175 }
1176 if (file_path == NULL((void*)0))
1177 {
1178 size_t dir_len = strlen (dir);
1179 memcpy (ptr, dir, dir_len + 1);
1180 ptr += dir_len + 1;
1181 }
1182
1183 optr = (unsigned char *) strchr (dir, 0) + 1;
1184 }
1185 optr++;
1186 *ptr++ = '\0';
1187
1188 /* file table */
1189 if (t->replace_files)
1190 {
1191 while (*optr != 0)
1192 {
1193 const char *file = (const char *) optr;
1194 const char *file_path = NULL((void*)0);
1195 if (t->replace_files)
1196 {
1197 file_path = skip_dir_prefix (file, base_dir);
1198 if (file_path != NULL((void*)0))
1199 {
1200 size_t dest_len = strlen (dest_dir);
1201 size_t file_len = strlen (file_path);
1202 memcpy (ptr, dest_dir, dest_len);
1203 ptr += dest_len;
1204 if (file_len > 0)
1205 {
1206 *ptr++ = '/';
1207 memcpy (ptr, file_path, file_len);
1208 ptr += file_len;
1209 }
1210 *ptr++ = '\0';
1211 }
1212 }
1213 if (file_path == NULL((void*)0))
1214 {
1215 size_t file_len = strlen (file);
1216 memcpy (ptr, file, file_len + 1);
1217 ptr += file_len + 1;
1218 }
1219
1220 optr = (unsigned char *) strchr (file, 0) + 1;
1221
1222 /* dir idx, time, len */
1223 uint32_t dir_idx = read_uleb128 (optr)({ unsigned int ret = 0; unsigned int c; int shift = 0; do { c
= *optr++; ret |= (c & 0x7f) << shift; shift += 7;
} while (c & 0x80); if (shift >= 35) ret = (2147483647
*2U +1U); ret; })
;
1224 write_uleb128 (ptr, dir_idx)({ uint32_t valv = (dir_idx); do { unsigned char c = valv &
0x7f; valv >>= 7; if (valv) c |= 0x80; *ptr++ = c; } while
(valv); })
;
1225 uint32_t time = read_uleb128 (optr)({ unsigned int ret = 0; unsigned int c; int shift = 0; do { c
= *optr++; ret |= (c & 0x7f) << shift; shift += 7;
} while (c & 0x80); if (shift >= 35) ret = (2147483647
*2U +1U); ret; })
;
1226 write_uleb128 (ptr, time)({ uint32_t valv = (time); do { unsigned char c = valv & 0x7f
; valv >>= 7; if (valv) c |= 0x80; *ptr++ = c; } while (
valv); })
;
1227 uint32_t len = read_uleb128 (optr)({ unsigned int ret = 0; unsigned int c; int shift = 0; do { c
= *optr++; ret |= (c & 0x7f) << shift; shift += 7;
} while (c & 0x80); if (shift >= 35) ret = (2147483647
*2U +1U); ret; })
;
1228 write_uleb128 (ptr, len)({ uint32_t valv = (len); do { unsigned char c = valv & 0x7f
; valv >>= 7; if (valv) c |= 0x80; *ptr++ = c; } while (
valv); })
;
1229 }
1230 optr++;
1231 *ptr++ = '\0';
1232 }
1233
1234 /* line number program (and file table if not copied above). */
1235 size_t remaining = (t->unit_length + 4
1236 - (optr - (old_buf + t->old_idx)));
1237 memcpy (ptr, optr, remaining);
1238 ptr += remaining;
1239 }
1240}
1241
1242/* Called during phase zero for each debug_line table referenced from
1243 .debug_info. Outputs all source files seen and records any
1244 adjustments needed in the debug_list data structures. Returns true
1245 if line_table needs to be rewrite either the dir or file paths. */
1246static bool_Bool
1247read_dwarf2_line (DSO *dso, uint32_t off, char *comp_dir)
1248{
1249 unsigned char *ptr, *dir;
1250 unsigned char **dirt;
1251 uint32_t value, dirt_cnt;
1252 size_t comp_dir_len = !comp_dir ? 0 : strlen (comp_dir);
1253 struct line_table *table;
1254
1255 if (get_line_table (dso, off, &table) == false0
1256 || table == NULL((void*)0))
1257 {
1258 if (table != NULL((void*)0))
1259 error (0, 0, ".debug_line offset 0x%x referenced multiple times",
1260 off);
1261 return false0;
1262 }
1263
1264 /* Skip to the directory table. The rest of the header has already
1265 been read and checked by get_line_table. */
1266 ptr = debug_sections[DEBUG_LINE2].data + off;
1267 ptr += (4 /* unit len */
1268 + 2 /* version */
1269 + 4 /* header len */
1270 + 1 /* min instr len */
1271 + (table->version >= 4) /* max op per instr, if version >= 4 */
1272 + 1 /* default is stmt */
1273 + 1 /* line base */
1274 + 1 /* line range */
1275 + 1 /* opcode base */
1276 + table->opcode_base - 1); /* opcode len table */
1277 dir = ptr;
1278
1279 /* dir table: */
1280 value = 1;
1281 while (*ptr != 0)
1282 {
1283 if (base_dir && dest_dir)
1284 {
1285 /* Do we need to replace any of the dirs? Calculate new size. */
1286 const char *file_path = skip_dir_prefix ((const char *)ptr,
1287 base_dir);
1288 if (file_path != NULL((void*)0))
1289 {
1290 size_t old_size = strlen ((const char *)ptr) + 1;
1291 size_t file_len = strlen (file_path);
1292 size_t new_size = strlen (dest_dir) + 1;
1293 if (file_len > 0)
1294 new_size += 1 + file_len;
1295 table->size_diff += (new_size - old_size);
1296 table->replace_dirs = true1;
1297 }
1298 }
1299
1300 ptr = (unsigned char *) strchr ((char *)ptr, 0) + 1;
1301 ++value;
1302 }
1303
1304 dirt = (unsigned char **) alloca (value * sizeof (unsigned char *))__builtin_alloca (value * sizeof (unsigned char *));
1305 dirt[0] = (unsigned char *) ".";
1306 dirt_cnt = 1;
1307 ptr = dir;
1308 while (*ptr != 0)
1309 {
1310 dirt[dirt_cnt++] = ptr;
1311 ptr = (unsigned char *) strchr ((char *)ptr, 0) + 1;
1312 }
1313 ptr++;
1314
1315 /* file table: */
1316 while (*ptr != 0)
1317 {
1318 char *s, *file;
1319 size_t file_len, dir_len;
1320
1321 file = (char *) ptr;
1322 ptr = (unsigned char *) strchr ((char *)ptr, 0) + 1;
1323 value = read_uleb128 (ptr)({ unsigned int ret = 0; unsigned int c; int shift = 0; do { c
= *ptr++; ret |= (c & 0x7f) << shift; shift += 7; }
while (c & 0x80); if (shift >= 35) ret = (2147483647 *
2U +1U); ret; })
;
1324
1325 if (value >= dirt_cnt)
1326 {
1327 error (0, 0, "%s: Wrong directory table index %u",
1328 dso->filename, value);
1329 return false0;
1330 }
1331 file_len = strlen (file);
1332 if (base_dir && dest_dir)
1333 {
1334 /* Do we need to replace any of the files? Calculate new size. */
1335 const char *file_path = skip_dir_prefix (file, base_dir);
1336 if (file_path != NULL((void*)0))
1337 {
1338 size_t old_size = file_len + 1;
1339 size_t file_len = strlen (file_path);
1340 size_t new_size = strlen (dest_dir) + 1;
1341 if (file_len > 0)
1342 new_size += 1 + file_len;
1343 table->size_diff += (new_size - old_size);
1344 table->replace_files = true1;
1345 }
1346 }
1347 dir_len = strlen ((char *)dirt[value]);
1348 s = malloc (comp_dir_len + 1 + file_len + 1 + dir_len + 1);
1349 if (s == NULL((void*)0))
1350 {
1351 error (0, ENOMEM12, "%s: Reading file table", dso->filename);
1352 return false0;
1353 }
1354 if (*file == '/')
1355 {
1356 memcpy (s, file, file_len + 1);
1357 }
1358 else if (*dirt[value] == '/')
1359 {
1360 memcpy (s, dirt[value], dir_len);
1361 s[dir_len] = '/';
1362 memcpy (s + dir_len + 1, file, file_len + 1);
1363 }
1364 else
1365 {
1366 char *p = s;
1367 if (comp_dir_len != 0)
1368 {
1369 memcpy (s, comp_dir, comp_dir_len);
1370 s[comp_dir_len] = '/';
1371 p += comp_dir_len + 1;
1372 }
1373 memcpy (p, dirt[value], dir_len);
1374 p[dir_len] = '/';
1375 memcpy (p + dir_len + 1, file, file_len + 1);
1376 }
1377 canonicalize_path (s, s);
1378 if (list_file_fd != -1)
1379 {
1380 const char *p = NULL((void*)0);
1381 if (base_dir == NULL((void*)0))
1382 p = s;
1383 else
1384 {
1385 p = skip_dir_prefix (s, base_dir);
1386 if (p == NULL((void*)0) && dest_dir != NULL((void*)0))
1387 p = skip_dir_prefix (s, dest_dir);
1388 }
1389
1390 if (p)
1391 {
1392 size_t size = strlen (p) + 1;
1393 while (size > 0)
1394 {
1395 ssize_t ret = write (list_file_fd, p, size);
1396 if (ret == -1)
1397 break;
1398 size -= ret;
1399 p += ret;
1400 }
1401 }
1402 }
1403
1404 free (s);
1405
1406 read_uleb128 (ptr)({ unsigned int ret = 0; unsigned int c; int shift = 0; do { c
= *ptr++; ret |= (c & 0x7f) << shift; shift += 7; }
while (c & 0x80); if (shift >= 35) ret = (2147483647 *
2U +1U); ret; })
;
1407 read_uleb128 (ptr)({ unsigned int ret = 0; unsigned int c; int shift = 0; do { c
= *ptr++; ret |= (c & 0x7f) << shift; shift += 7; }
while (c & 0x80); if (shift >= 35) ret = (2147483647 *
2U +1U); ret; })
;
1408 }
1409
1410 dso->lines.debug_lines_len += 4 + table->unit_length + table->size_diff;
1411 return table->replace_dirs || table->replace_files;
1412}
1413
1414/* Called during phase one, after the table has been sorted. */
1415static size_t
1416find_new_list_offs (struct debug_lines *lines, size_t idx)
1417{
1418 struct line_table key;
1419 key.old_idx = idx;
1420 struct line_table *table = bsearch (&key, lines->table,
1421 lines->used,
1422 sizeof (struct line_table),
1423 line_table_cmp);
1424 return table->new_idx;
1425}
1426
1427/* This scans the attributes of one DIE described by the given abbrev_tag.
1428 PTR points to the data in the debug_info. It will be advanced till all
1429 abbrev data is consumed. In phase zero data is collected, in phase one
1430 data might be replaced/updated. */
1431static unsigned char *
1432edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase)
1433{
1434 int i;
1435 uint32_t list_offs;
1436 int found_list_offs;
1437 char *comp_dir;
1438
1439 comp_dir = NULL((void*)0);
1440 list_offs = 0;
1441 found_list_offs = 0;
1442 for (i = 0; i < t->nattr; ++i)
1443 {
1444 uint32_t form = t->attr[i].form;
1445 size_t len = 0;
1446 while (1)
1447 {
1448 /* Whether we already handled a string as file for this
1449 attribute. If we did then we don't need to handle/record
1450 it again when handling the DW_FORM_strp later. */
1451 bool_Bool handled_strp = false0;
1452
1453 /* A stmt_list points into the .debug_line section. In
1454 phase zero record all offsets. Then in phase one replace
1455 them with the new offsets if we rewrote the line
1456 tables. */
1457 if (t->attr[i].attr == DW_AT_stmt_list)
1458 {
1459 if (form == DW_FORM_data4
1460 || form == DW_FORM_sec_offset0x17)
1461 {
1462 list_offs = do_read_32_relocated (ptr)({ uint32_t dret = do_read_32 (ptr); if (relptr) { while (relptr
< relend && relptr->ptr < ptr) ++relptr; if
(relptr < relend && relptr->ptr == ptr) { if (
reltype == 9) dret += relptr->addend; else dret = relptr->
addend; } } dret; })
;
1463 if (phase == 0)
1464 found_list_offs = 1;
1465 else if (need_stmt_update) /* phase one */
1466 {
1467 size_t idx, new_idx;
1468 idx = do_read_32_relocated (ptr)({ uint32_t dret = do_read_32 (ptr); if (relptr) { while (relptr
< relend && relptr->ptr < ptr) ++relptr; if
(relptr < relend && relptr->ptr == ptr) { if (
reltype == 9) dret += relptr->addend; else dret = relptr->
addend; } } dret; })
;
1469 new_idx = find_new_list_offs (&dso->lines, idx);
1470 do_write_32_relocated (ptr, new_idx)({ if (relptr && relptr < relend && relptr
->ptr == ptr) { if (reltype == 9) do_write_32 (ptr, new_idx
- relptr->addend); else relptr->addend = new_idx; } else
do_write_32 (ptr,new_idx); })
;
1471 }
1472 }
1473 }
1474
1475 /* DW_AT_comp_dir is the current working directory. */
1476 if (t->attr[i].attr == DW_AT_comp_dir)
1477 {
1478 if (form == DW_FORM_string)
1479 {
1480 free (comp_dir);
1481 comp_dir = strdup ((char *)ptr);
1482
1483 if (dest_dir)
1484 {
1485 /* In phase zero we are just collecting dir/file
1486 names and check whether any need to be
1487 adjusted. If so, in phase one we replace
1488 those dir/files. */
1489 const char *file = skip_dir_prefix (comp_dir, base_dir);
1490 if (file != NULL((void*)0) && phase == 0)
1491 need_string_replacement = true1;
1492 else if (file != NULL((void*)0) && phase == 1)
1493 {
1494 size_t orig_len = strlen (comp_dir);
1495 size_t dest_len = strlen (dest_dir);
1496 size_t file_len = strlen (file);
1497 size_t new_len = dest_len;
1498 if (file_len > 0)
1499 new_len += 1 + file_len; /* + '/' */
1500
1501 /* We don't want to rewrite the whole
1502 debug_info section, so we only replace
1503 the comp_dir with something equal or
1504 smaller, possibly adding some slashes
1505 at the end of the new compdir. This
1506 normally doesn't happen since most
1507 producers will use DW_FORM_strp which is
1508 more efficient. */
1509 if (orig_len < new_len)
1510 fprintf (stderrstderr, "Warning, not replacing comp_dir "
1511 "'%s' prefix ('%s' -> '%s') encoded as "
1512 "DW_FORM_string. "
1513 "Replacement too large.\n",
1514 comp_dir, base_dir, dest_dir);
1515 else
1516 {
1517 /* Add zero (if no file part), one or more
1518 slashes in between the new dest_dir and the
1519 file name to fill up all space (replacement
1520 DW_FORM_string must be of the same length).
1521 We don't need to copy the old file name (if
1522 any) or the zero terminator, because those
1523 are already at the end of the string. */
1524 memcpy (ptr, dest_dir, dest_len);
1525 memset (ptr + dest_len, '/',
1526 orig_len - new_len);
1527 }
1528 }
1529 }
1530 }
1531 else if (form == DW_FORM_strp &&
1532 debug_sections[DEBUG_STR8].data)
1533 {
1534 const char *dir;
1535 size_t idx = do_read_32_relocated (ptr)({ uint32_t dret = do_read_32 (ptr); if (relptr) { while (relptr
< relend && relptr->ptr < ptr) ++relptr; if
(relptr < relend && relptr->ptr == ptr) { if (
reltype == 9) dret += relptr->addend; else dret = relptr->
addend; } } dret; })
;
1536 dir = (char *) debug_sections[DEBUG_STR8].data + idx;
1537
1538 free (comp_dir);
1539 comp_dir = strdup (dir);
1540
1541 if (dest_dir != NULL((void*)0) && phase == 0)
1542 {
1543 if (record_file_string_entry_idx (&dso->strings, idx))
1544 need_strp_update = true1;
1545 handled_strp = true1;
1546 }
1547 }
1548 }
1549 else if ((t->tag == DW_TAG_compile_unit
1550 || t->tag == DW_TAG_partial_unit0x3c)
1551 && t->attr[i].attr == DW_AT_name
1552 && form == DW_FORM_strp
1553 && debug_sections[DEBUG_STR8].data)
1554 {
1555 /* DW_AT_name is the primary file for this compile
1556 unit. If starting with / it is a full path name.
1557 Note that we don't handle DW_FORM_string in this
1558 case. */
1559 char *name;
1560 size_t idx = do_read_32_relocated (ptr)({ uint32_t dret = do_read_32 (ptr); if (relptr) { while (relptr
< relend && relptr->ptr < ptr) ++relptr; if
(relptr < relend && relptr->ptr == ptr) { if (
reltype == 9) dret += relptr->addend; else dret = relptr->
addend; } } dret; })
;
1561 name = (char *) debug_sections[DEBUG_STR8].data + idx;
1562 if (*name == '/' && comp_dir == NULL((void*)0))
1563 {
1564 char *enddir = strrchr (name, '/');
1565
1566 if (enddir != name)
1567 {
1568 comp_dir = malloc (enddir - name + 1);
1569 memcpy (comp_dir, name, enddir - name);
1570 comp_dir [enddir - name] = '\0';
1571 }
1572 else
1573 comp_dir = strdup ("/");
1574 }
1575
1576 /* First pass (0) records the new name to be
1577 added to the debug string pool, the second
1578 pass (1) stores it (the new index). */
1579 if (dest_dir && phase == 0)
1580 {
1581 if (record_file_string_entry_idx (&dso->strings, idx))
1582 need_strp_update = true1;
1583 handled_strp = true1;
1584 }
1585 }
1586
1587 switch (form)
1588 {
1589 case DW_FORM_ref_addr:
1590 if (cu_version == 2)
1591 ptr += ptr_size;
1592 else
1593 ptr += 4;
1594 break;
1595 case DW_FORM_flag_present0x19:
1596 break;
1597 case DW_FORM_addr:
1598 ptr += ptr_size;
1599 break;
1600 case DW_FORM_ref1:
1601 case DW_FORM_flag:
1602 case DW_FORM_data1:
1603 ++ptr;
1604 break;
1605 case DW_FORM_ref2:
1606 case DW_FORM_data2:
1607 ptr += 2;
1608 break;
1609 case DW_FORM_ref4:
1610 case DW_FORM_data4:
1611 case DW_FORM_sec_offset0x17:
1612 ptr += 4;
1613 break;
1614 case DW_FORM_ref8:
1615 case DW_FORM_data8:
1616 case DW_FORM_ref_sig80x20:
1617 ptr += 8;
1618 break;
1619 case DW_FORM_sdata:
1620 case DW_FORM_ref_udata:
1621 case DW_FORM_udata:
1622 read_uleb128 (ptr)({ unsigned int ret = 0; unsigned int c; int shift = 0; do { c
= *ptr++; ret |= (c & 0x7f) << shift; shift += 7; }
while (c & 0x80); if (shift >= 35) ret = (2147483647 *
2U +1U); ret; })
;
1623 break;
1624 case DW_FORM_strp:
1625 /* In the first pass we collect all strings, in the
1626 second we put the new references back (if there are
1627 any changes). */
1628 if (phase == 0)
1629 {
1630 /* handled_strp is set for attributes referring to
1631 files. If it is set the string is already
1632 recorded. */
1633 if (! handled_strp)
1634 {
1635 size_t idx = do_read_32_relocated (ptr)({ uint32_t dret = do_read_32 (ptr); if (relptr) { while (relptr
< relend && relptr->ptr < ptr) ++relptr; if
(relptr < relend && relptr->ptr == ptr) { if (
reltype == 9) dret += relptr->addend; else dret = relptr->
addend; } } dret; })
;
1636 record_existing_string_entry_idx (&dso->strings, idx);
1637 }
1638 }
1639 else if (need_strp_update) /* && phase == 1 */
1640 {
1641 struct stridxentry *entry;
1642 size_t idx, new_idx;
1643 idx = do_read_32_relocated (ptr)({ uint32_t dret = do_read_32 (ptr); if (relptr) { while (relptr
< relend && relptr->ptr < ptr) ++relptr; if
(relptr < relend && relptr->ptr == ptr) { if (
reltype == 9) dret += relptr->addend; else dret = relptr->
addend; } } dret; })
;
1644 entry = string_find_entry (&dso->strings, idx);
1645 new_idx = strent_offsetdwelf_strent_off (entry->entry);
1646 do_write_32_relocated (ptr, new_idx)({ if (relptr && relptr < relend && relptr
->ptr == ptr) { if (reltype == 9) do_write_32 (ptr, new_idx
- relptr->addend); else relptr->addend = new_idx; } else
do_write_32 (ptr,new_idx); })
;
1647 }
1648 ptr += 4;
1649 break;
1650 case DW_FORM_string:
1651 ptr = (unsigned char *) strchr ((char *)ptr, '\0') + 1;
1652 break;
1653 case DW_FORM_indirect:
1654 form = read_uleb128 (ptr)({ unsigned int ret = 0; unsigned int c; int shift = 0; do { c
= *ptr++; ret |= (c & 0x7f) << shift; shift += 7; }
while (c & 0x80); if (shift >= 35) ret = (2147483647 *
2U +1U); ret; })
;
1655 continue;
1656 case DW_FORM_block1:
1657 len = *ptr++;
1658 break;
1659 case DW_FORM_block2:
1660 len = read_16 (ptr)({ uint16_t ret = do_read_16 (ptr); ptr += 2; ret; });
1661 form = DW_FORM_block1;
1662 break;
1663 case DW_FORM_block4:
1664 len = read_32 (ptr)({ uint32_t ret = do_read_32 (ptr); ptr += 4; ret; });
1665 form = DW_FORM_block1;
1666 break;
1667 case DW_FORM_block:
1668 case DW_FORM_exprloc0x18:
1669 len = read_uleb128 (ptr)({ unsigned int ret = 0; unsigned int c; int shift = 0; do { c
= *ptr++; ret |= (c & 0x7f) << shift; shift += 7; }
while (c & 0x80); if (shift >= 35) ret = (2147483647 *
2U +1U); ret; })
;
1670 form = DW_FORM_block1;
1671 assert (len < UINT_MAX)({ if (len < (2147483647 *2U +1U)) ; else __assert_fail ("len < UINT_MAX"
, "tools/debugedit.c", 1671, __PRETTY_FUNCTION__); })
;
1672 break;
1673 default:
1674 error (0, 0, "%s: Unknown DWARF DW_FORM_%d", dso->filename,
1675 form);
1676 return NULL((void*)0);
1677 }
1678
1679 if (form == DW_FORM_block1)
1680 ptr += len;
1681
1682 break;
1683 }
1684 }
1685
1686 /* Ensure the CU current directory will exist even if only empty. Source
1687 filenames possibly located in its parent directories refer relatively to
1688 it and the debugger (GDB) cannot safely optimize out the missing
1689 CU current dir subdirectories. Only do this once in phase one. And
1690 only do this for dirs under our build/base_dir. Don't output the
1691 empty string (in case the comp_dir == base_dir). */
1692 if (phase == 0 && base_dir && comp_dir && list_file_fd != -1)
1693 {
1694 const char *p = skip_dir_prefix (comp_dir, base_dir);
1695 if (p != NULL((void*)0) && p[0] != '\0')
1696 {
1697 size_t size = strlen (p) + 1;
1698 while (size > 0)
1699 {
1700 ssize_t ret = write (list_file_fd, p, size);
1701 if (ret == -1)
1702 break;
1703 size -= ret;
1704 p += ret;
1705 }
1706 }
1707 }
1708
1709 /* In phase zero we collect all file names (we need the comp_dir for
1710 that). Note that calculating the new size and offsets is done
1711 separately (at the end of phase zero after all CUs have been
1712 scanned in dwarf2_edit). */
1713 if (phase == 0 && found_list_offs
1714 && read_dwarf2_line (dso, list_offs, comp_dir))
1715 need_stmt_update = true1;
1716
1717 free (comp_dir);
1718
1719 return ptr;
1720}
1721
1722static int
1723rel_cmp (const void *a, const void *b)
1724{
1725 REL *rela = (REL *) a, *relb = (REL *) b;
1726
1727 if (rela->ptr < relb->ptr)
1728 return -1;
1729
1730 if (rela->ptr > relb->ptr)
1731 return 1;
1732
1733 return 0;
1734}
1735
1736static int
1737line_rel_cmp (const void *a, const void *b)
1738{
1739 LINE_REL *rela = (LINE_REL *) a, *relb = (LINE_REL *) b;
1740
1741 if (rela->r_offset < relb->r_offset)
1742 return -1;
1743
1744 if (rela->r_offset > relb->r_offset)
1745 return 1;
1746
1747 return 0;
1748}
1749
1750static int
1751edit_dwarf2 (DSO *dso)
1752{
1753 Elf_Data *data;
1754 Elf_Scn *scn;
1755 int i, j;
1756
1757 for (i = 0; debug_sections[i].name; ++i)
1758 {
1759 debug_sections[i].data = NULL((void*)0);
1760 debug_sections[i].size = 0;
1761 debug_sections[i].sec = 0;
1762 debug_sections[i].relsec = 0;
1763 }
1764 ptr_size = 0;
1765
1766 for (i = 1; i < dso->ehdr.e_shnum; ++i)
1767 if (! (dso->shdr[i].sh_flags & (SHF_ALLOC(1 << 1) | SHF_WRITE(1 << 0) | SHF_EXECINSTR(1 << 2)))
1768 && dso->shdr[i].sh_size)
1769 {
1770 const char *name = strptr (dso, dso->ehdr.e_shstrndx,
1771 dso->shdr[i].sh_name);
1772
1773 if (strncmp (name, ".debug_", sizeof (".debug_") - 1) == 0)
1774 {
1775 for (j = 0; debug_sections[j].name; ++j)
1776 if (strcmp (name, debug_sections[j].name) == 0)
1777 {
1778 if (debug_sections[j].data)
1779 {
1780 error (0, 0, "%s: Found two copies of %s section",
1781 dso->filename, name);
1782 return 1;
1783 }
1784
1785 scn = dso->scn[i];
1786 data = elf_getdata (scn, NULL((void*)0));
1787 assert (data != NULL && data->d_buf != NULL)({ if (data != ((void*)0) && data->d_buf != ((void
*)0)) ; else __assert_fail ("data != NULL && data->d_buf != NULL"
, "tools/debugedit.c", 1787, __PRETTY_FUNCTION__); })
;
1788 assert (elf_getdata (scn, data) == NULL)({ if (elf_getdata (scn, data) == ((void*)0)) ; else __assert_fail
("elf_getdata (scn, data) == NULL", "tools/debugedit.c", 1788
, __PRETTY_FUNCTION__); })
;
1789 assert (data->d_off == 0)({ if (data->d_off == 0) ; else __assert_fail ("data->d_off == 0"
, "tools/debugedit.c", 1789, __PRETTY_FUNCTION__); })
;
1790 assert (data->d_size == dso->shdr[i].sh_size)({ if (data->d_size == dso->shdr[i].sh_size) ; else __assert_fail
("data->d_size == dso->shdr[i].sh_size", "tools/debugedit.c"
, 1790, __PRETTY_FUNCTION__); })
;
1791 debug_sections[j].data = data->d_buf;
1792 debug_sections[j].elf_data = data;
1793 debug_sections[j].size = data->d_size;
1794 debug_sections[j].sec = i;
1795 break;
1796 }
1797
1798 if (debug_sections[j].name == NULL((void*)0))
1799 {
1800 error (0, 0, "%s: Unknown debugging section %s",
1801 dso->filename, name);
1802 }
1803 }
1804 else if (dso->ehdr.e_type == ET_REL1
1805 && ((dso->shdr[i].sh_type == SHT_REL9
1806 && strncmp (name, ".rel.debug_",
1807 sizeof (".rel.debug_") - 1) == 0)
1808 || (dso->shdr[i].sh_type == SHT_RELA4
1809 && strncmp (name, ".rela.debug_",
1810 sizeof (".rela.debug_") - 1) == 0)))
1811 {
1812 for (j = 0; debug_sections[j].name; ++j)
1813 if (strcmp (name + sizeof (".rel") - 1
1814 + (dso->shdr[i].sh_type == SHT_RELA4),
1815 debug_sections[j].name) == 0)
1816 {
1817 debug_sections[j].relsec = i;
1818 break;
1819 }
1820 }
1821 }
1822
1823 if (dso->ehdr.e_ident[EI_DATA5] == ELFDATA2LSB1)
1824 {
1825 do_read_16 = buf_read_ule16;
1826 do_read_32 = buf_read_ule32;
1827 do_write_16 = dwarf2_write_le16;
1828 do_write_32 = dwarf2_write_le32;
1829 }
1830 else if (dso->ehdr.e_ident[EI_DATA5] == ELFDATA2MSB2)
1831 {
1832 do_read_16 = buf_read_ube16;
1833 do_read_32 = buf_read_ube32;
1834 do_write_16 = dwarf2_write_be16;
1835 do_write_32 = dwarf2_write_be32;
1836 }
1837 else
1838 {
1839 error (0, 0, "%s: Wrong ELF data enconding", dso->filename);
1840 return 1;
1841 }
1842
1843 if (debug_sections[DEBUG_INFO0].data != NULL((void*)0))
1844 {
1845 unsigned char *ptr, *endcu, *endsec;
1846 uint32_t value;
1847 htab_t abbrev;
1848 struct abbrev_tag tag, *t;
1849 int phase;
1850 REL *relbuf = NULL((void*)0);
1851
1852 if (debug_sections[DEBUG_INFO0].relsec)
1853 {
1854 int ndx, maxndx;
1855 GElf_Rel rel;
1856 GElf_Rela rela;
1857 GElf_Sym sym;
1858 GElf_Addr base = dso->shdr[debug_sections[DEBUG_INFO0].sec].sh_addr;
1859 Elf_Data *symdata = NULL((void*)0);
1860 int rtype;
1861
1862 i = debug_sections[DEBUG_INFO0].relsec;
1863 scn = dso->scn[i];
1864 data = elf_getdata (scn, NULL((void*)0));
1865 assert (data != NULL && data->d_buf != NULL)({ if (data != ((void*)0) && data->d_buf != ((void
*)0)) ; else __assert_fail ("data != NULL && data->d_buf != NULL"
, "tools/debugedit.c", 1865, __PRETTY_FUNCTION__); })
;
1866 assert (elf_getdata (scn, data) == NULL)({ if (elf_getdata (scn, data) == ((void*)0)) ; else __assert_fail
("elf_getdata (scn, data) == NULL", "tools/debugedit.c", 1866
, __PRETTY_FUNCTION__); })
;
1867 assert (data->d_off == 0)({ if (data->d_off == 0) ; else __assert_fail ("data->d_off == 0"
, "tools/debugedit.c", 1867, __PRETTY_FUNCTION__); })
;
1868 assert (data->d_size == dso->shdr[i].sh_size)({ if (data->d_size == dso->shdr[i].sh_size) ; else __assert_fail
("data->d_size == dso->shdr[i].sh_size", "tools/debugedit.c"
, 1868, __PRETTY_FUNCTION__); })
;
1869 maxndx = dso->shdr[i].sh_size / dso->shdr[i].sh_entsize;
1870 relbuf = malloc (maxndx * sizeof (REL));
1871 reltype = dso->shdr[i].sh_type;
1872 if (relbuf == NULL((void*)0))
1873 error (1, errno(*__errno_location ()), "%s: Could not allocate memory", dso->filename);
1874
1875 symdata = elf_getdata (dso->scn[dso->shdr[i].sh_link], NULL((void*)0));
1876 assert (symdata != NULL && symdata->d_buf != NULL)({ if (symdata != ((void*)0) && symdata->d_buf != (
(void*)0)) ; else __assert_fail ("symdata != NULL && symdata->d_buf != NULL"
, "tools/debugedit.c", 1876, __PRETTY_FUNCTION__); })
;
1877 assert (elf_getdata (dso->scn[dso->shdr[i].sh_link], symdata)({ if (elf_getdata (dso->scn[dso->shdr[i].sh_link], symdata
) == ((void*)0)) ; else __assert_fail ("elf_getdata (dso->scn[dso->shdr[i].sh_link], symdata) == NULL"
, "tools/debugedit.c", 1878, __PRETTY_FUNCTION__); })
1878 == NULL)({ if (elf_getdata (dso->scn[dso->shdr[i].sh_link], symdata
) == ((void*)0)) ; else __assert_fail ("elf_getdata (dso->scn[dso->shdr[i].sh_link], symdata) == NULL"
, "tools/debugedit.c", 1878, __PRETTY_FUNCTION__); })
;
1879 assert (symdata->d_off == 0)({ if (symdata->d_off == 0) ; else __assert_fail ("symdata->d_off == 0"
, "tools/debugedit.c", 1879, __PRETTY_FUNCTION__); })
;
1880 assert (symdata->d_size({ if (symdata->d_size == dso->shdr[dso->shdr[i].sh_link
].sh_size) ; else __assert_fail ("symdata->d_size == dso->shdr[dso->shdr[i].sh_link].sh_size"
, "tools/debugedit.c", 1881, __PRETTY_FUNCTION__); })
1881 == dso->shdr[dso->shdr[i].sh_link].sh_size)({ if (symdata->d_size == dso->shdr[dso->shdr[i].sh_link
].sh_size) ; else __assert_fail ("symdata->d_size == dso->shdr[dso->shdr[i].sh_link].sh_size"
, "tools/debugedit.c", 1881, __PRETTY_FUNCTION__); })
;
1882
1883 for (ndx = 0, relend = relbuf; ndx < maxndx; ++ndx)
1884 {
1885 if (dso->shdr[i].sh_type == SHT_REL9)
1886 {
1887 gelf_getrel (data, ndx, &rel);
1888 rela.r_offset = rel.r_offset;
1889 rela.r_info = rel.r_info;
1890 rela.r_addend = 0;
1891 }
1892 else
1893 gelf_getrela (data, ndx, &rela);
1894 gelf_getsym (symdata, ELF64_R_SYM (rela.r_info)((rela.r_info) >> 32), &sym);
1895 /* Relocations against section symbols are uninteresting
1896 in REL. */
1897 if (dso->shdr[i].sh_type == SHT_REL9 && sym.st_value == 0)
1898 continue;
1899 /* Only consider relocations against .debug_str, .debug_line
1900 and .debug_abbrev. */
1901 if (sym.st_shndx != debug_sections[DEBUG_STR8].sec
1902 && sym.st_shndx != debug_sections[DEBUG_LINE2].sec
1903 && sym.st_shndx != debug_sections[DEBUG_ABBREV1].sec)
1904 continue;
1905 rela.r_addend += sym.st_value;
1906 rtype = ELF64_R_TYPE (rela.r_info)((rela.r_info) & 0xffffffff);
1907 switch (dso->ehdr.e_machine)
1908 {
1909 case EM_SPARC2:
1910 case EM_SPARC32PLUS18:
1911 case EM_SPARCV943:
1912 if (rtype != R_SPARC_323 && rtype != R_SPARC_UA3223)
1913 goto fail;
1914 break;
1915 case EM_3863:
1916 if (rtype != R_386_321)
1917 goto fail;
1918 break;
1919 case EM_PPC20:
1920 case EM_PPC6421:
1921 if (rtype != R_PPC_ADDR321 && rtype != R_PPC_UADDR3224)
1922 goto fail;
1923 break;
1924 case EM_S39022:
1925 if (rtype != R_390_324)
1926 goto fail;
1927 break;
1928 case EM_IA_6450:
1929 if (rtype != R_IA64_SECREL32LSB0x65)
1930 goto fail;
1931 break;
1932 case EM_X86_6462:
1933 if (rtype != R_X86_64_3210)
1934 goto fail;
1935 break;
1936 case EM_ALPHA0x9026:
1937 if (rtype != R_ALPHA_REFLONG1)
1938 goto fail;
1939 break;
1940#if defined(EM_AARCH64183) && defined(R_AARCH64_ABS32258)
1941 case EM_AARCH64183:
1942 if (rtype != R_AARCH64_ABS32258)
1943 goto fail;
1944 break;
1945#endif
1946 case EM_68K4:
1947 if (rtype != R_68K_321)
1948 goto fail;
1949 break;
1950 default:
1951 fail:
1952 error (1, 0, "%s: Unhandled relocation %d in .debug_info section",
1953 dso->filename, rtype);
1954 }
1955 relend->ptr = debug_sections[DEBUG_INFO0].data
1956 + (rela.r_offset - base);
1957 relend->addend = rela.r_addend;
1958 relend->ndx = ndx;
1959 ++relend;
1960 }
1961 if (relbuf == relend)
1962 {
1963 free (relbuf);
1964 relbuf = NULL((void*)0);
1965 relend = NULL((void*)0);
1966 }
1967 else
1968 qsort (relbuf, relend - relbuf, sizeof (REL), rel_cmp);
1969 }
1970
1971 for (phase = 0; phase < 2; phase++)
1972 {
1973 /* If we don't need to update anyhing, skip phase 1. */
1974 if (phase == 1
1975 && !need_strp_update
1976 && !need_string_replacement
1977 && !need_stmt_update)
1978 break;
1979
1980 ptr = debug_sections[DEBUG_INFO0].data;
1981 relptr = relbuf;
1982 endsec = ptr + debug_sections[DEBUG_INFO0].size;
1983 while (ptr < endsec)
1984 {
1985 if (ptr + 11 > endsec)
1986 {
1987 error (0, 0, "%s: .debug_info CU header too small",
1988 dso->filename);
1989 return 1;
1990 }
1991
1992 endcu = ptr + 4;
1993 endcu += read_32 (ptr)({ uint32_t ret = do_read_32 (ptr); ptr += 4; ret; });
1994 if (endcu == ptr + 0xffffffff)
1995 {
1996 error (0, 0, "%s: 64-bit DWARF not supported", dso->filename);
1997 return 1;
1998 }
1999
2000 if (endcu > endsec)
2001 {
2002 error (0, 0, "%s: .debug_info too small", dso->filename);
2003 return 1;
2004 }
2005
2006 cu_version = read_16 (ptr)({ uint16_t ret = do_read_16 (ptr); ptr += 2; ret; });
2007 if (cu_version != 2 && cu_version != 3 && cu_version != 4)
2008 {
2009 error (0, 0, "%s: DWARF version %d unhandled", dso->filename,
2010 cu_version);
2011 return 1;
2012 }
2013
2014 value = read_32_relocated (ptr)({ uint32_t ret = ({ uint32_t dret = do_read_32 (ptr); if (relptr
) { while (relptr < relend && relptr->ptr < ptr
) ++relptr; if (relptr < relend && relptr->ptr ==
ptr) { if (reltype == 9) dret += relptr->addend; else dret
= relptr->addend; } } dret; }); ptr += 4; ret; })
;
2015 if (value >= debug_sections[DEBUG_ABBREV1].size)
2016 {
2017 if (debug_sections[DEBUG_ABBREV1].data == NULL((void*)0))
2018 error (0, 0, "%s: .debug_abbrev not present", dso->filename);
2019 else
2020 error (0, 0, "%s: DWARF CU abbrev offset too large",
2021 dso->filename);
2022 return 1;
2023 }
2024
2025 if (ptr_size == 0)
2026 {
2027 ptr_size = read_8 (ptr)*ptr++;
2028 if (ptr_size != 4 && ptr_size != 8)
2029 {
2030 error (0, 0, "%s: Invalid DWARF pointer size %d",
2031 dso->filename, ptr_size);
2032 return 1;
2033 }
2034 }
2035 else if (read_8 (ptr)*ptr++ != ptr_size)
2036 {
2037 error (0, 0, "%s: DWARF pointer size differs between CUs",
2038 dso->filename);
2039 return 1;
2040 }
2041
2042 abbrev = read_abbrev (dso,
2043 debug_sections[DEBUG_ABBREV1].data + value);
2044 if (abbrev == NULL((void*)0))
2045 return 1;
2046
2047 while (ptr < endcu)
2048 {
2049 tag.entry = read_uleb128 (ptr)({ unsigned int ret = 0; unsigned int c; int shift = 0; do { c
= *ptr++; ret |= (c & 0x7f) << shift; shift += 7; }
while (c & 0x80); if (shift >= 35) ret = (2147483647 *
2U +1U); ret; })
;
2050 if (tag.entry == 0)
2051 continue;
2052 t = htab_find_with_hash (abbrev, &tag, tag.entry);
2053 if (t == NULL((void*)0))
2054 {
2055 error (0, 0, "%s: Could not find DWARF abbreviation %d",
2056 dso->filename, tag.entry);
2057 htab_delete (abbrev);
2058 return 1;
2059 }
2060
2061 ptr = edit_attributes (dso, ptr, t, phase);
2062 if (ptr == NULL((void*)0))
2063 break;
2064 }
2065
2066 htab_delete (abbrev);
2067 }
2068
2069 /* We might have to recalculate/rewrite the debug_line
2070 section. We need to do that before going into phase one
2071 so we have all new offsets. We do this separately from
2072 scanning the dirs/file names because the DW_AT_stmt_lists
2073 might not be in order or skip some padding we might have
2074 to (re)move. */
2075 if (phase == 0 && need_stmt_update)
2076 {
2077 edit_dwarf2_line (dso);
2078
2079 /* The line table programs will be moved
2080 forward/backwards a bit in the new data. Update the
2081 debug_line relocations to the new offsets. */
2082 int rndx = debug_sections[DEBUG_LINE2].relsec;
2083 if (rndx != 0)
2084 {
2085 LINE_REL *rbuf;
2086 size_t rels;
2087 Elf_Data *rdata = elf_getdata (dso->scn[rndx], NULL((void*)0));
2088 int rtype = dso->shdr[rndx].sh_type;
2089 rels = dso->shdr[rndx].sh_size / dso->shdr[rndx].sh_entsize;
2090 rbuf = malloc (rels * sizeof (LINE_REL));
2091 if (rbuf == NULL((void*)0))
2092 error (1, errno(*__errno_location ()), "%s: Could not allocate line relocations",
2093 dso->filename);
2094
2095 /* Sort them by offset into section. */
2096 for (size_t i = 0; i < rels; i++)
2097 {
2098 if (rtype == SHT_RELA4)
2099 {
2100 GElf_Rela rela;
2101 if (gelf_getrela (rdata, i, &rela) == NULL((void*)0))
2102 error (1, 0, "Couldn't get relocation: %s",
2103 elf_errmsg (-1));
2104 rbuf[i].r_offset = rela.r_offset;
2105 rbuf[i].ndx = i;
2106 }
2107 else
2108 {
2109 GElf_Rel rel;
2110 if (gelf_getrel (rdata, i, &rel) == NULL((void*)0))
2111 error (1, 0, "Couldn't get relocation: %s",
2112 elf_errmsg (-1));
2113 rbuf[i].r_offset = rel.r_offset;
2114 rbuf[i].ndx = i;
2115 }
2116 }
2117 qsort (rbuf, rels, sizeof (LINE_REL), line_rel_cmp);
2118
2119 size_t lndx = 0;
2120 for (size_t i = 0; i < rels; i++)
2121 {
2122 /* These relocations only happen in ET_REL files
2123 and are section offsets. */
2124 GElf_Addr r_offset;
2125 size_t ndx = rbuf[i].ndx;
2126
2127 GElf_Rel rel;
2128 GElf_Rela rela;
2129 if (rtype == SHT_RELA4)
2130 {
2131 if (gelf_getrela (rdata, ndx, &rela) == NULL((void*)0))
2132 error (1, 0, "Couldn't get relocation: %s",
2133 elf_errmsg (-1));
2134 r_offset = rela.r_offset;
2135 }
2136 else
2137 {
2138 if (gelf_getrel (rdata, ndx, &rel) == NULL((void*)0))
2139 error (1, 0, "Couldn't get relocation: %s",
2140 elf_errmsg (-1));
2141 r_offset = rel.r_offset;
2142 }
2143
2144 while (r_offset > (dso->lines.table[lndx].old_idx
2145 + 4
2146 + dso->lines.table[lndx].unit_length)
2147 && lndx < dso->lines.used)
2148 lndx++;
2149
2150 if (lndx >= dso->lines.used)
2151 error (1, 0,
2152 ".debug_line relocation offset out of range");
2153
2154 /* Offset (pointing into the line program) moves
2155 from old to new index including the header
2156 size diff. */
2157 r_offset += ((dso->lines.table[lndx].new_idx
2158 - dso->lines.table[lndx].old_idx)
2159 + dso->lines.table[lndx].size_diff);
2160
2161 if (rtype == SHT_RELA4)
2162 {
2163 rela.r_offset = r_offset;
2164 if (gelf_update_rela (rdata, ndx, &rela) == 0)
2165 error (1, 0, "Couldn't update relocation: %s",
2166 elf_errmsg (-1));
2167 }
2168 else
2169 {
2170 rel.r_offset = r_offset;
2171 if (gelf_update_rel (rdata, ndx, &rel) == 0)
2172 error (1, 0, "Couldn't update relocation: %s",
2173 elf_errmsg (-1));
2174 }
2175 }
2176
2177 elf_flagdata (rdata, ELF_C_SET, ELF_F_DIRTYELF_F_DIRTY);
2178 free (rbuf);
2179 }
2180 }
2181
2182 /* Same for the debug_str section. Make sure everything is
2183 in place for phase 1 updating of debug_info
2184 references. */
2185 if (phase == 0 && need_strp_update)
2186 {
2187 Strtab *strtab = dso->strings.str_tab;
2188 Elf_Data *strdata = debug_sections[DEBUG_STR8].elf_data;
2189 int strndx = debug_sections[DEBUG_STR8].sec;
2190 Elf_Scn *strscn = dso->scn[strndx];
2191
2192 /* Out with the old. */
2193 strdata->d_size = 0;
2194 /* In with the new. */
2195 strdata = elf_newdata (strscn);
2196
2197 /* We really should check whether we had enough memory,
2198 but the old ebl version will just abort on out of
2199 memory... */
2200 strtab_finalizedwelf_strtab_finalize (strtab, strdata);
2201 debug_sections[DEBUG_STR8].size = strdata->d_size;
2202 dso->strings.str_buf = strdata->d_buf;
2203 }
2204
2205 }
2206
2207 /* After phase 1 we might have rewritten the debug_info with
2208 new strp, strings and/or linep offsets. */
2209 if (need_strp_update || need_string_replacement || need_stmt_update)
2210 dirty_section (DEBUG_INFO0);
2211
2212 /* Update any debug_info relocations addends we might have touched. */
2213 if (relbuf != NULL((void*)0) && reltype == SHT_RELA4)
2214 {
2215 Elf_Data *symdata;
2216 int relsec_ndx = debug_sections[DEBUG_INFO0].relsec;
2217 data = elf_getdata (dso->scn[relsec_ndx], NULL((void*)0));
2218 symdata = elf_getdata (dso->scn[dso->shdr[relsec_ndx].sh_link],
2219 NULL((void*)0));
2220
2221 relptr = relbuf;
2222 while (relptr < relend)
2223 {
2224 GElf_Sym sym;
2225 GElf_Rela rela;
2226 int ndx = relptr->ndx;
2227
2228 if (gelf_getrela (data, ndx, &rela) == NULL((void*)0))
2229 error (1, 0, "Couldn't get relocation: %s",
2230 elf_errmsg (-1));
2231
2232 if (gelf_getsym (symdata, GELF_R_SYM (rela.r_info)((rela.r_info) >> 32),
2233 &sym) == NULL((void*)0))
2234 error (1, 0, "Couldn't get symbol: %s", elf_errmsg (-1));
2235
2236 rela.r_addend = relptr->addend - sym.st_value;
2237
2238 if (gelf_update_rela (data, ndx, &rela) == 0)
2239 error (1, 0, "Couldn't update relocations: %s",
2240 elf_errmsg (-1));
2241
2242 ++relptr;
2243 }
2244 elf_flagdata (data, ELF_C_SET, ELF_F_DIRTYELF_F_DIRTY);
2245 }
2246
2247 free (relbuf);
2248 }
2249
2250 return 0;
2251}
2252
2253static struct poptOption optionsTable[] = {
2254 { "base-dir", 'b', POPT_ARG_STRING1U, &base_dir, 0,
2255 "base build directory of objects", NULL((void*)0) },
2256 { "dest-dir", 'd', POPT_ARG_STRING1U, &dest_dir, 0,
2257 "directory to rewrite base-dir into", NULL((void*)0) },
2258 { "list-file", 'l', POPT_ARG_STRING1U, &list_file, 0,
2259 "file where to put list of source and header file names", NULL((void*)0) },
2260 { "build-id", 'i', POPT_ARG_NONE0U, &do_build_id, 0,
2261 "recompute build ID note and print ID on stdout", NULL((void*)0) },
2262 { "build-id-seed", 's', POPT_ARG_STRING1U, &build_id_seed, 0,
2263 "if recomputing the build ID note use this string as hash seed", NULL((void*)0) },
2264 { "no-recompute-build-id", 'n', POPT_ARG_NONE0U, &no_recompute_build_id, 0,
2265 "do not recompute build ID note even when -i or -s are given", NULL((void*)0) },
2266 POPT_AUTOHELP{ ((void*)0), '\0', 4U, poptHelpOptions, 0, "Help options:", (
(void*)0) },
2267 { NULL((void*)0), 0, 0, NULL((void*)0), 0, NULL((void*)0), NULL((void*)0) }
2268};
2269
2270static DSO *
2271fdopen_dso (int fd, const char *name)
2272{
2273 Elf *elf = NULL((void*)0);
2274 GElf_Ehdr ehdr;
2275 int i;
2276 DSO *dso = NULL((void*)0);
2277 size_t phnum;
2278
2279 elf = elf_begin (fd, ELF_C_RDWR, NULL((void*)0));
2280 if (elf == NULL((void*)0))
2281 {
2282 error (0, 0, "cannot open ELF file: %s", elf_errmsg (-1));
2283 goto error_out;
2284 }
2285
2286 if (elf_kind (elf) != ELF_K_ELF)
2287 {
2288 error (0, 0, "\"%s\" is not an ELF file", name);
2289 goto error_out;
2290 }
2291
2292 if (gelf_getehdr (elf, &ehdr) == NULL((void*)0))
2293 {
2294 error (0, 0, "cannot get the ELF header: %s",
2295 elf_errmsg (-1));
2296 goto error_out;
2297 }
2298
2299 if (ehdr.e_type != ET_DYN3 && ehdr.e_type != ET_EXEC2 && ehdr.e_type != ET_REL1)
2300 {
2301 error (0, 0, "\"%s\" is not a shared library", name);
2302 goto error_out;
2303 }
2304
2305 /* Allocate DSO structure. Leave place for additional 20 new section
2306 headers. */
2307 dso = (DSO *)
2308 malloc (sizeof(DSO) + (ehdr.e_shnum + 20) * sizeof(GElf_Shdr)
2309 + (ehdr.e_shnum + 20) * sizeof(Elf_Scn *));
2310 if (!dso)
2311 {
2312 error (0, ENOMEM12, "Could not open DSO");
2313 goto error_out;
2314 }
2315
2316 if (elf_getphdrnum (elf, &phnum) != 0)
2317 {
2318 error (0, 0, "Couldn't get number of phdrs: %s", elf_errmsg (-1));
2319 goto error_out;
2320 }
2321
2322 /* If there are phdrs we want to maintain the layout of the
2323 allocated sections in the file. */
2324 if (phnum != 0)
2325 elf_flagelf (elf, ELF_C_SET, ELF_F_LAYOUTELF_F_LAYOUT);
2326
2327 memset (dso, 0, sizeof(DSO));
2328 dso->elf = elf;
2329 dso->phnum = phnum;
2330 dso->ehdr = ehdr;
2331 dso->scn = (Elf_Scn **) &dso->shdr[ehdr.e_shnum + 20];
2332
2333 for (i = 0; i < ehdr.e_shnum; ++i)
2334 {
2335 dso->scn[i] = elf_getscn (elf, i);
2336 gelf_getshdr (dso->scn[i], dso->shdr + i);
2337 }
2338
2339 dso->filename = (const char *) strdup (name);
2340 setup_strings (&dso->strings);
2341 setup_lines (&dso->lines);
2342 return dso;
2343
2344error_out:
2345 if (dso)
2346 {
2347 free ((char *) dso->filename);
2348 destroy_strings (&dso->strings);
2349 destroy_lines (&dso->lines);
2350 free (dso);
2351 }
2352 if (elf)
2353 elf_end (elf);
2354 if (fd != -1)
2355 close (fd);
2356 return NULL((void*)0);
2357}
2358
2359static const pgpHashAlgo algorithms[] = { PGPHASHALGO_MD5,
2360 PGPHASHALGO_SHA1, PGPHASHALGO_SHA256, PGPHASHALGO_SHA384, PGPHASHALGO_SHA512 };
2361
2362/* Compute a fresh build ID bit-string from the editted file contents. */
2363static void
2364handle_build_id (DSO *dso, Elf_Data *build_id,
2365 size_t build_id_offset, size_t build_id_size)
2366{
2367 DIGEST_CTX ctx;
2368 pgpHashAlgo algorithm;
2369 int i = sizeof(algorithms)/sizeof(algorithms[0]);
2370 void *digest = NULL((void*)0);
2371 size_t len;
2372
2373 while (i-- > 0)
2374 {
2375 algorithm = algorithms[i];
2376 if (rpmDigestLength(algorithm) == build_id_size)
2377 break;
2378 }
2379 if (i < 0)
2380 {
2381 fprintf (stderrstderr, "Cannot handle %Zu-byte build ID\n", build_id_size);
2382 exit (1);
2383 }
2384
2385 if (no_recompute_build_id
2386 || (! dirty_elf && build_id_seed == NULL((void*)0)))
2387 goto print;
2388
2389 /* Clear the old bits so they do not affect the new hash. */
2390 memset ((char *) build_id->d_buf + build_id_offset, 0, build_id_size);
2391
2392 ctx = rpmDigestInit(algorithm, 0);
2393
2394 /* If a seed string was given use it to prime the hash. */
2395 if (build_id_seed != NULL((void*)0))
2396 rpmDigestUpdate(ctx, build_id_seed, strlen (build_id_seed));
2397
2398 /* Slurp the relevant header bits and section contents and feed them
2399 into the hash function. The only bits we ignore are the offset
2400 fields in ehdr and shdrs, since the semantically identical ELF file
2401 could be written differently if it doesn't change the phdr layout.
2402 We always use the GElf (i.e. Elf64) formats for the bits to hash
2403 since it is convenient. It doesn't matter whether this is an Elf32
2404 or Elf64 object, only that we are consistent in what bits feed the
2405 hash so it comes out the same for the same file contents. */
2406 {
2407 union
2408 {
2409 GElf_Ehdr ehdr;
2410 GElf_Phdr phdr;
2411 GElf_Shdr shdr;
2412 } u;
2413 Elf_Data x = { .d_version = EV_CURRENT1, .d_buf = &u };
2414
2415 x.d_type = ELF_T_EHDR;
2416 x.d_size = sizeof u.ehdr;
2417 u.ehdr = dso->ehdr;
2418 u.ehdr.e_phoff = u.ehdr.e_shoff = 0;
2419 if (elf64_xlatetom (&x, &x, dso->ehdr.e_ident[EI_DATA5]) == NULL((void*)0))
2420 {
2421 bad:
2422 fprintf (stderrstderr, "Failed to compute header checksum: %s\n",
2423 elf_errmsg (elf_errno ()));
2424 exit (1);
2425 }
2426
2427 x.d_type = ELF_T_PHDR;
2428 x.d_size = sizeof u.phdr;
2429 for (i = 0; i < dso->ehdr.e_phnum; ++i)
2430 {
2431 if (gelf_getphdr (dso->elf, i, &u.phdr) == NULL((void*)0))
2432 goto bad;
2433 if (elf64_xlatetom (&x, &x, dso->ehdr.e_ident[EI_DATA5]) == NULL((void*)0))
2434 goto bad;
2435 rpmDigestUpdate(ctx, x.d_buf, x.d_size);
2436 }
2437
2438 x.d_type = ELF_T_SHDR;
2439 x.d_size = sizeof u.shdr;
2440 for (i = 0; i < dso->ehdr.e_shnum; ++i)
2441 if (dso->scn[i] != NULL((void*)0))
2442 {
2443 u.shdr = dso->shdr[i];
2444 u.shdr.sh_offset = 0;
2445 if (elf64_xlatetom (&x, &x, dso->ehdr.e_ident[EI_DATA5]) == NULL((void*)0))
2446 goto bad;
2447 rpmDigestUpdate(ctx, x.d_buf, x.d_size);
2448
2449 if (u.shdr.sh_type != SHT_NOBITS8)
2450 {
2451 Elf_Data *d = elf_getdata (dso->scn[i], NULL((void*)0));
2452 if (d == NULL((void*)0))
2453 goto bad;
2454 rpmDigestUpdate(ctx, d->d_buf, d->d_size);
2455 }
2456 }
2457 }
2458
2459 rpmDigestFinal(ctx, &digest, &len, 0);
2460 memcpy((unsigned char *)build_id->d_buf + build_id_offset, digest, build_id_size);
2461 free(digest);
2462
2463 elf_flagdata (build_id, ELF_C_SET, ELF_F_DIRTYELF_F_DIRTY);
2464
2465 print:
2466 /* Now format the build ID bits in hex to print out. */
2467 {
2468 const uint8_t * id = (uint8_t *)build_id->d_buf + build_id_offset;
2469 char *hex = pgpHexStr(id, build_id_size);
2470 puts (hex);
2471 free(hex);
2472 }
2473}
2474
2475int
2476main (int argc, char *argv[])
2477{
2478 DSO *dso;
2479 int fd, i;
2480 const char *file;
2481 poptContext optCon; /* context for parsing command-line options */
2482 int nextopt;
2483 const char **args;
2484 struct stat stat_buf;
2485 Elf_Data *build_id = NULL((void*)0);
2486 size_t build_id_offset = 0, build_id_size = 0;
2487
2488 optCon = poptGetContext("debugedit", argc, (const char **)argv, optionsTable, 0);
2489
2490 while ((nextopt = poptGetNextOpt (optCon)) > 0 || nextopt == POPT_ERROR_BADOPT-11)
2491 /* do nothing */ ;
2492
2493 if (nextopt != -1)
2494 {
2495 fprintf (stderrstderr, "Error on option %s: %s.\nRun '%s --help' to see a full list of available command line options.\n",
2496 poptBadOption (optCon, 0),
2497 poptStrerror (nextopt),
2498 argv[0]);
2499 exit (1);
2500 }
2501
2502 args = poptGetArgs (optCon);
2503 if (args == NULL((void*)0) || args[0] == NULL((void*)0) || args[1] != NULL((void*)0))
2504 {
2505 poptPrintHelp(optCon, stdoutstdout, 0);
2506 exit (1);
2507 }
2508
2509 if (dest_dir != NULL((void*)0))
2510 {
2511 if (base_dir == NULL((void*)0))
2512 {
2513 fprintf (stderrstderr, "You must specify a base dir if you specify a dest dir\n");
2514 exit (1);
2515 }
2516 }
2517
2518 if (build_id_seed != NULL((void*)0) && do_build_id == 0)
2519 {
2520 fprintf (stderrstderr, "--build-id-seed (-s) needs --build-id (-i)\n");
2521 exit (1);
2522 }
2523
2524 if (build_id_seed != NULL((void*)0) && strlen (build_id_seed) < 1)
2525 {
2526 fprintf (stderrstderr,
2527 "--build-id-seed (-s) string should be at least 1 char\n");
2528 exit (1);
2529 }
2530
2531 /* Ensure clean paths, users can muck with these. Also removes any
2532 trailing '/' from the paths. */
2533 if (base_dir)
2534 canonicalize_path(base_dir, base_dir);
2535 if (dest_dir)
2536 canonicalize_path(dest_dir, dest_dir);
2537
2538 if (list_file != NULL((void*)0))
2539 {
2540 list_file_fd = open (list_file, O_WRONLY01|O_CREAT0100|O_APPEND02000, 0644);
2541 }
2542
2543 file = args[0];
2544
2545 if (elf_version(EV_CURRENT1) == EV_NONE0)
2546 {
2547 fprintf (stderrstderr, "library out of date\n");
2548 exit (1);
2549 }
2550
2551 if (stat(file, &stat_buf) < 0)
2552 {
2553 fprintf (stderrstderr, "Failed to open input file '%s': %s\n", file, strerror(errno(*__errno_location ())));
2554 exit (1);
2555 }
2556
2557 /* Make sure we can read and write */
2558 chmod (file, stat_buf.st_mode | S_IRUSR0400 | S_IWUSR0200);
2559
2560 fd = open (file, O_RDWR02);
2561 if (fd < 0)
2562 {
2563 fprintf (stderrstderr, "Failed to open input file '%s': %s\n", file, strerror(errno(*__errno_location ())));
2564 exit (1);
2565 }
2566
2567 dso = fdopen_dso (fd, file);
2568 if (dso == NULL((void*)0))
2569 exit (1);
2570
2571 for (i = 1; i < dso->ehdr.e_shnum; i++)
2572 {
2573 const char *name;
2574
2575 switch (dso->shdr[i].sh_type)
2576 {
2577 case SHT_PROGBITS1:
2578 name = strptr (dso, dso->ehdr.e_shstrndx, dso->shdr[i].sh_name);
2579 /* TODO: Handle stabs */
2580 if (strcmp (name, ".stab") == 0)
2581 {
2582 fprintf (stderrstderr, "Stabs debuginfo not supported: %s\n", file);
2583 break;
2584 }
2585 if (strcmp (name, ".debug_info") == 0)
2586 edit_dwarf2 (dso);
2587
2588 break;
2589 case SHT_NOTE7:
2590 if (do_build_id
2591 && build_id == 0 && (dso->shdr[i].sh_flags & SHF_ALLOC(1 << 1)))
2592 {
2593 /* Look for a build-ID note here. */
2594 size_t off = 0;
2595 GElf_Nhdr nhdr;
2596 size_t name_off;
2597 size_t desc_off;
2598 Elf_Data *data = elf_getdata (elf_getscn (dso->elf, i), NULL((void*)0));
2599 while ((off = gelf_getnote (data, off,
2600 &nhdr, &name_off, &desc_off)) > 0)
2601 if (nhdr.n_type == NT_GNU_BUILD_ID3
2602 && nhdr.n_namesz == sizeof "GNU"
2603 && (memcmp ((char *)data->d_buf + name_off, "GNU",
2604 sizeof "GNU") == 0))
2605 {
2606 build_id = data;
2607 build_id_offset = desc_off;
2608 build_id_size = nhdr.n_descsz;
2609 }
2610 }
2611 break;
2612 default:
2613 break;
2614 }
2615 }
2616
2617 /* Normally we only need to explicitly update the section headers
2618 and data when any section data changed size. But because of a bug
2619 in elfutils before 0.169 we will have to update and write out all
2620 section data if any data has changed (when ELF_F_LAYOUT was
2621 set). https://sourceware.org/bugzilla/show_bug.cgi?id=21199 */
2622 bool_Bool need_update = need_strp_update || need_stmt_update;
2623
2624#if !_ELFUTILS_PREREQ (0, 169)(169 >= ((0) * 1000 + (169)))
2625 /* string replacements or build_id updates don't change section size. */
2626 need_update = (need_update
2627 || need_string_replacement
2628 || (do_build_id && build_id != NULL((void*)0)));
2629#endif
2630
2631 /* We might have changed the size of some debug sections. If so make
2632 sure the section headers are updated and the data offsets are
2633 correct. We set ELF_F_LAYOUT above because we don't want libelf
2634 to move any allocated sections around itself if there are any
2635 phdrs. Which means we are responsible for setting the section size
2636 and offset fields. Plus the shdr offsets. We don't want to change
2637 anything for the phdrs allocated sections. Keep the offset of
2638 allocated sections so they are at the same place in the file. Add
2639 unallocated ones after the allocated ones. */
2640 if (dso->phnum != 0 && need_update)
2641 {
2642 Elf *elf = dso->elf;
2643 GElf_Off last_offset;
2644 /* We position everything after the phdrs (which normally would
2645 be at the start of the ELF file after the ELF header. */
2646 last_offset = (dso->ehdr.e_phoff + gelf_fsize (elf, ELF_T_PHDR,
2647 dso->phnum, EV_CURRENT1));
2648
2649 /* First find the last allocated section. */
2650 Elf_Scn *scn = NULL((void*)0);
2651 while ((scn = elf_nextscn (elf, scn)) != NULL((void*)0))
2652 {
2653 GElf_Shdr shdr_mem;
2654 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
2655 if (shdr == NULL((void*)0))
2656 error (1, 0, "Couldn't get shdr: %s\n", elf_errmsg (-1));
2657
2658 /* Any sections we have changed aren't allocated sections,
2659 so we don't need to lookup any changed section sizes. */
2660 if ((shdr->sh_flags & SHF_ALLOC(1 << 1)) != 0)
2661 {
2662 GElf_Off off = shdr->sh_offset + (shdr->sh_type != SHT_NOBITS8
2663 ? shdr->sh_size : 0);
2664 if (last_offset < off)
2665 last_offset = off;
2666 }
2667 }
2668
2669 /* Now adjust any sizes and offsets for the unallocated sections. */
2670 scn = NULL((void*)0);
2671 while ((scn = elf_nextscn (elf, scn)) != NULL((void*)0))
2672 {
2673 GElf_Shdr shdr_mem;
2674 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
2675 if (shdr == NULL((void*)0))
2676 error (1, 0, "Couldn't get shdr: %s\n", elf_errmsg (-1));
2677
2678 /* A bug in elfutils before 0.169 means we have to write out
2679 all section data, even when nothing changed.
2680 https://sourceware.org/bugzilla/show_bug.cgi?id=21199 */
2681#if !_ELFUTILS_PREREQ (0, 169)(169 >= ((0) * 1000 + (169)))
2682 if (shdr->sh_type != SHT_NOBITS8)
2683 {
2684 Elf_Data *d = elf_getdata (scn, NULL((void*)0));
2685 elf_flagdata (d, ELF_C_SET, ELF_F_DIRTYELF_F_DIRTY);
2686 }
2687#endif
2688 if ((shdr->sh_flags & SHF_ALLOC(1 << 1)) == 0)
2689 {
2690 GElf_Off sec_offset = shdr->sh_offset;
Value stored to 'sec_offset' during its initialization is never read
2691 GElf_Xword sec_size = shdr->sh_size;
2692
2693 /* We might have changed the size (and content) of the
2694 debug_str or debug_line section. */
2695 size_t secnum = elf_ndxscn (scn);
2696 if (secnum == debug_sections[DEBUG_STR8].sec)
2697 sec_size = debug_sections[DEBUG_STR8].size;
2698 if (secnum == debug_sections[DEBUG_LINE2].sec)
2699 sec_size = debug_sections[DEBUG_LINE2].size;
2700
2701 /* Zero means one. No alignment constraints. */
2702 size_t addralign = shdr->sh_addralign ?: 1;
2703 last_offset = (last_offset + addralign - 1) & ~(addralign - 1);
2704 sec_offset = last_offset;
2705 if (shdr->sh_type != SHT_NOBITS8)
2706 last_offset += sec_size;
2707
2708 if (shdr->sh_size != sec_size
2709 || shdr->sh_offset != sec_offset)
2710 {
2711 /* Make sure unchanged section data is written out
2712 at the new location. */
2713 if (shdr->sh_offset != sec_offset
2714 && shdr->sh_type != SHT_NOBITS8)
2715 {
2716 Elf_Data *d = elf_getdata (scn, NULL((void*)0));
2717 elf_flagdata (d, ELF_C_SET, ELF_F_DIRTYELF_F_DIRTY);
2718 }
2719
2720 shdr->sh_size = sec_size;
2721 shdr->sh_offset = sec_offset;
2722 if (gelf_update_shdr (scn, shdr) == 0)
2723 error (1, 0, "Couldn't update shdr: %s\n",
2724 elf_errmsg (-1));
2725 }
2726 }
2727 }
2728
2729 /* Position the shdrs after the last (unallocated) section. */
2730 const size_t offsize = gelf_fsize (elf, ELF_T_OFF, 1, EV_CURRENT1);
2731 GElf_Off new_offset = ((last_offset + offsize - 1)
2732 & ~((GElf_Off) (offsize - 1)));
2733 if (dso->ehdr.e_shoff != new_offset)
2734 {
2735 dso->ehdr.e_shoff = new_offset;
2736 if (gelf_update_ehdr (elf, &dso->ehdr) == 0)
2737 error (1, 0, "Couldn't update ehdr: %s\n", elf_errmsg (-1));
2738 }
2739 }
2740
2741 if (elf_update (dso->elf, ELF_C_NULL) < 0)
2742 {
2743 fprintf (stderrstderr, "Failed to update file: %s\n",
2744 elf_errmsg (elf_errno ()));
2745 exit (1);
2746 }
2747
2748 if (do_build_id && build_id != NULL((void*)0))
2749 handle_build_id (dso, build_id, build_id_offset, build_id_size);
2750
2751 if (elf_update (dso->elf, ELF_C_WRITE) < 0)
2752 {
2753 fprintf (stderrstderr, "Failed to write file: %s\n", elf_errmsg (elf_errno()));
2754 exit (1);
2755 }
2756 if (elf_end (dso->elf) < 0)
2757 {
2758 fprintf (stderrstderr, "elf_end failed: %s\n", elf_errmsg (elf_errno()));
2759 exit (1);
2760 }
2761 close (fd);
2762
2763 /* Restore old access rights */
2764 chmod (file, stat_buf.st_mode);
2765
2766 free ((char *) dso->filename);
2767 destroy_strings (&dso->strings);
2768 destroy_lines (&dso->lines);
2769 free (dso);
2770
2771 poptFreeContext (optCon);
2772
2773 return 0;
2774}