]> git.ipfire.org Git - pakfire.git/blob - src/debugedit/debugedit.c
75b48f0b9a0eb27310902a270aefc5c7bf901eb3
[pakfire.git] / src / debugedit / debugedit.c
1 /* Copyright (C) 2001, 2002, 2003, 2005, 2007, 2009 Red Hat, Inc.
2 Written by Alexander Larsson <alexl@redhat.com>, 2002
3 Based on code by Jakub Jelinek <jakub@redhat.com>, 2001.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software Foundation,
17 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18
19 /* Needed for libelf */
20 #define _FILE_OFFSET_BITS 64
21
22 #include <assert.h>
23 #include <byteswap.h>
24 #include <endian.h>
25 #include <errno.h>
26 #include <error.h>
27 #include <limits.h>
28 #include <string.h>
29 #include <stdlib.h>
30 #include <unistd.h>
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <fcntl.h>
34 #include <popt.h>
35
36 #include <gelf.h>
37
38 /* some defines taken from the dwarf standard */
39
40 #define DW_TAG_compile_unit 0x11
41
42 #define DW_AT_name 0x03
43 #define DW_AT_stmt_list 0x10
44 #define DW_AT_comp_dir 0x1b
45
46 #define DW_FORM_addr 0x01
47 #define DW_FORM_block2 0x03
48 #define DW_FORM_block4 0x04
49 #define DW_FORM_data2 0x05
50 #define DW_FORM_data4 0x06
51 #define DW_FORM_data8 0x07
52 #define DW_FORM_string 0x08
53 #define DW_FORM_block 0x09
54 #define DW_FORM_block1 0x0a
55 #define DW_FORM_data1 0x0b
56 #define DW_FORM_flag 0x0c
57 #define DW_FORM_sdata 0x0d
58 #define DW_FORM_strp 0x0e
59 #define DW_FORM_udata 0x0f
60 #define DW_FORM_ref_addr 0x10
61 #define DW_FORM_ref1 0x11
62 #define DW_FORM_ref2 0x12
63 #define DW_FORM_ref4 0x13
64 #define DW_FORM_ref8 0x14
65 #define DW_FORM_ref_udata 0x15
66 #define DW_FORM_indirect 0x16
67
68 #include <beecrypt/beecrypt.h>
69 #include "hashtab.h"
70 #include "rpmtag.h"
71
72 #define DW_TAG_partial_unit 0x3c
73 #define DW_FORM_sec_offset 0x17
74 #define DW_FORM_exprloc 0x18
75 #define DW_FORM_flag_present 0x19
76 #define DW_FORM_ref_sig8 0x20
77
78 char *base_dir = NULL;
79 char *dest_dir = NULL;
80 char *list_file = NULL;
81 int list_file_fd = -1;
82 int do_build_id = 0;
83
84 typedef struct
85 {
86 Elf *elf;
87 GElf_Ehdr ehdr;
88 Elf_Scn **scn;
89 const char *filename;
90 int lastscn;
91 GElf_Shdr shdr[0];
92 } DSO;
93
94 typedef struct
95 {
96 unsigned char *ptr;
97 rpmuint32_t addend;
98 } REL;
99
100 #define read_uleb128(ptr) ({ \
101 unsigned int ret = 0; \
102 unsigned int c; \
103 int shift = 0; \
104 do \
105 { \
106 c = *ptr++; \
107 ret |= (c & 0x7f) << shift; \
108 shift += 7; \
109 } while (c & 0x80); \
110 \
111 if (shift >= 35) \
112 ret = UINT_MAX; \
113 ret; \
114 })
115
116 static rpmuint16_t (*do_read_16) (unsigned char *ptr);
117 static rpmuint32_t (*do_read_32) (unsigned char *ptr);
118 static void (*write_32) (unsigned char *ptr, GElf_Addr val);
119
120 static int ptr_size;
121 static int cu_version;
122
123 static inline rpmuint16_t
124 buf_read_ule16 (unsigned char *data)
125 {
126 return data[0] | (data[1] << 8);
127 }
128
129 static inline rpmuint16_t
130 buf_read_ube16 (unsigned char *data)
131 {
132 return data[1] | (data[0] << 8);
133 }
134
135 static inline rpmuint32_t
136 buf_read_ule32 (unsigned char *data)
137 {
138 return data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
139 }
140
141 static inline rpmuint32_t
142 buf_read_ube32 (unsigned char *data)
143 {
144 return data[3] | (data[2] << 8) | (data[1] << 16) | (data[0] << 24);
145 }
146
147 static const char *
148 strptr (DSO *dso, int sec, off_t offset)
149 {
150 Elf_Scn *scn;
151 Elf_Data *data;
152
153 scn = dso->scn[sec];
154 if (offset >= 0 && (GElf_Addr) offset < dso->shdr[sec].sh_size)
155 {
156 data = NULL;
157 while ((data = elf_rawdata (scn, data)) != NULL)
158 {
159 if (data->d_buf
160 && offset >= data->d_off
161 && offset < data->d_off + (off_t)data->d_size)
162 return (const char *) data->d_buf + (offset - data->d_off);
163 }
164 }
165
166 return NULL;
167 }
168
169
170 #define read_1(ptr) *ptr++
171
172 #define read_16(ptr) ({ \
173 rpmuint16_t ret = do_read_16 (ptr); \
174 ptr += 2; \
175 ret; \
176 })
177
178 #define read_32(ptr) ({ \
179 rpmuint32_t ret = do_read_32 (ptr); \
180 ptr += 4; \
181 ret; \
182 })
183
184 REL *relptr, *relend;
185 int reltype;
186
187 #define do_read_32_relocated(ptr) ({ \
188 rpmuint32_t dret = do_read_32 (ptr); \
189 if (relptr) \
190 { \
191 while (relptr < relend && relptr->ptr < ptr) \
192 ++relptr; \
193 if (relptr < relend && relptr->ptr == ptr) \
194 { \
195 if (reltype == SHT_REL) \
196 dret += relptr->addend; \
197 else \
198 dret = relptr->addend; \
199 } \
200 } \
201 dret; \
202 })
203
204 #define read_32_relocated(ptr) ({ \
205 rpmuint32_t ret = do_read_32_relocated (ptr); \
206 ptr += 4; \
207 ret; \
208 })
209
210 static void
211 dwarf2_write_le32 (unsigned char *p, GElf_Addr val)
212 {
213 rpmuint32_t v = (rpmuint32_t) val;
214
215 p[0] = v;
216 p[1] = v >> 8;
217 p[2] = v >> 16;
218 p[3] = v >> 24;
219 }
220
221
222 static void
223 dwarf2_write_be32 (unsigned char *p, GElf_Addr val)
224 {
225 rpmuint32_t v = (rpmuint32_t) val;
226
227 p[3] = v;
228 p[2] = v >> 8;
229 p[1] = v >> 16;
230 p[0] = v >> 24;
231 }
232
233 static struct
234 {
235 const char *name;
236 unsigned char *data;
237 Elf_Data *elf_data;
238 size_t size;
239 int sec, relsec;
240 } debug_sections[] =
241 {
242 #define DEBUG_INFO 0
243 #define DEBUG_ABBREV 1
244 #define DEBUG_LINE 2
245 #define DEBUG_ARANGES 3
246 #define DEBUG_PUBNAMES 4
247 #define DEBUG_PUBTYPES 5
248 #define DEBUG_MACINFO 6
249 #define DEBUG_LOC 7
250 #define DEBUG_STR 8
251 #define DEBUG_FRAME 9
252 #define DEBUG_RANGES 10
253 #define DEBUG_TYPES 11
254 #define DEBUG_MACRO 12
255 { ".debug_info", NULL, NULL, 0, 0, 0 },
256 { ".debug_abbrev", NULL, NULL, 0, 0, 0 },
257 { ".debug_line", NULL, NULL, 0, 0, 0 },
258 { ".debug_aranges", NULL, NULL, 0, 0, 0 },
259 { ".debug_pubnames", NULL, NULL, 0, 0, 0 },
260 { ".debug_pubtypes", NULL, NULL, 0, 0, 0 },
261 { ".debug_macinfo", NULL, NULL, 0, 0, 0 },
262 { ".debug_loc", NULL, NULL, 0, 0, 0 },
263 { ".debug_str", NULL, NULL, 0, 0, 0 },
264 { ".debug_frame", NULL, NULL, 0, 0, 0 },
265 { ".debug_ranges", NULL, NULL, 0, 0, 0 },
266 { ".debug_types", NULL, NULL, 0, 0, 0 },
267 { ".debug_macro", NULL, NULL, 0, 0, 0 },
268 { NULL, NULL, NULL, 0, 0, 0 }
269 };
270
271 struct abbrev_attr
272 {
273 unsigned int attr;
274 unsigned int form;
275 };
276
277 struct abbrev_tag
278 {
279 unsigned int entry;
280 unsigned int tag;
281 int nattr;
282 struct abbrev_attr attr[0];
283 };
284
285 static hashval_t
286 abbrev_hash (const void *p)
287 {
288 struct abbrev_tag *t = (struct abbrev_tag *)p;
289
290 return t->entry;
291 }
292
293 static int
294 abbrev_eq (const void *p, const void *q)
295 {
296 struct abbrev_tag *t1 = (struct abbrev_tag *)p;
297 struct abbrev_tag *t2 = (struct abbrev_tag *)q;
298
299 return t1->entry == t2->entry;
300 }
301
302 static void
303 abbrev_del (void *p)
304 {
305 free (p);
306 }
307
308 static htab_t
309 read_abbrev (DSO *dso, unsigned char *ptr)
310 {
311 htab_t h = htab_try_create (50, abbrev_hash, abbrev_eq, abbrev_del);
312 unsigned int attr, form;
313 struct abbrev_tag *t;
314 int size;
315 void **slot;
316
317 if (h == NULL)
318 {
319 no_memory:
320 error (0, ENOMEM, "%s: Could not read .debug_abbrev", dso->filename);
321 if (h)
322 htab_delete (h);
323 return NULL;
324 }
325
326 while ((attr = read_uleb128 (ptr)) != 0)
327 {
328 size = 10;
329 t = malloc (sizeof (*t) + size * sizeof (struct abbrev_attr));
330 if (t == NULL)
331 goto no_memory;
332 t->entry = attr;
333 t->nattr = 0;
334 slot = htab_find_slot (h, t, INSERT);
335 if (slot == NULL)
336 {
337 free (t);
338 goto no_memory;
339 }
340 if (*slot != NULL)
341 {
342 error (0, 0, "%s: Duplicate DWARF abbreviation %d", dso->filename,
343 t->entry);
344 free (t);
345 htab_delete (h);
346 return NULL;
347 }
348 t->tag = read_uleb128 (ptr);
349 ++ptr; /* skip children flag. */
350 while ((attr = read_uleb128 (ptr)) != 0)
351 {
352 if (t->nattr == size)
353 {
354 size += 10;
355 t = realloc (t, sizeof (*t) + size * sizeof (struct abbrev_attr));
356 if (t == NULL)
357 goto no_memory;
358 }
359 form = read_uleb128 (ptr);
360 if (form == 2
361 || (form > DW_FORM_flag_present && form != DW_FORM_ref_sig8))
362 {
363 error (0, 0, "%s: Unknown DWARF DW_FORM_%d", dso->filename, form);
364 htab_delete (h);
365 return NULL;
366 }
367
368 t->attr[t->nattr].attr = attr;
369 t->attr[t->nattr++].form = form;
370 }
371 if (read_uleb128 (ptr) != 0)
372 {
373 error (0, 0, "%s: DWARF abbreviation does not end with 2 zeros",
374 dso->filename);
375 htab_delete (h);
376 return NULL;
377 }
378 *slot = t;
379 }
380
381 return h;
382 }
383
384 #define IS_DIR_SEPARATOR(c) ((c)=='/')
385
386 static char *
387 canonicalize_path (const char *s, char *d)
388 {
389 char *rv = d;
390 const char *sroot;
391 char *droot;
392
393 if (IS_DIR_SEPARATOR (*s))
394 {
395 *d++ = *s++;
396 if (IS_DIR_SEPARATOR (*s) && !IS_DIR_SEPARATOR (s[1]))
397 {
398 /* Special case for "//foo" meaning a Posix namespace
399 escape. */
400 *d++ = *s++;
401 }
402 while (IS_DIR_SEPARATOR (*s))
403 s++;
404 }
405 droot = d;
406 sroot = s;
407
408 while (*s)
409 {
410 /* At this point, we're always at the beginning of a path
411 segment. */
412
413 if (s[0] == '.' && (s[1] == 0 || IS_DIR_SEPARATOR (s[1])))
414 {
415 s++;
416 if (*s)
417 while (IS_DIR_SEPARATOR (*s))
418 ++s;
419 }
420
421 else if (s[0] == '.' && s[1] == '.'
422 && (s[2] == 0 || IS_DIR_SEPARATOR (s[2])))
423 {
424 char *pre = d - 1; /* includes slash */
425 while (droot < pre && IS_DIR_SEPARATOR (*pre))
426 pre--;
427 if (droot <= pre && ! IS_DIR_SEPARATOR (*pre))
428 {
429 while (droot < pre && ! IS_DIR_SEPARATOR (*pre))
430 pre--;
431 /* pre now points to the slash */
432 if (droot < pre)
433 pre++;
434 if (pre + 3 == d && pre[0] == '.' && pre[1] == '.')
435 {
436 *d++ = *s++;
437 *d++ = *s++;
438 }
439 else
440 {
441 d = pre;
442 s += 2;
443 if (*s)
444 while (IS_DIR_SEPARATOR (*s))
445 s++;
446 }
447 }
448 else
449 {
450 *d++ = *s++;
451 *d++ = *s++;
452 }
453 }
454 else
455 {
456 while (*s && ! IS_DIR_SEPARATOR (*s))
457 *d++ = *s++;
458 }
459
460 if (IS_DIR_SEPARATOR (*s))
461 {
462 *d++ = *s++;
463 while (IS_DIR_SEPARATOR (*s))
464 s++;
465 }
466 }
467 while (droot < d && IS_DIR_SEPARATOR (d[-1]))
468 --d;
469 if (d == rv)
470 *d++ = '.';
471 *d = 0;
472
473 return rv;
474 }
475
476 static int
477 has_prefix (const char *str,
478 const char *prefix)
479 {
480 size_t str_len;
481 size_t prefix_len;
482
483 str_len = strlen (str);
484 prefix_len = strlen (prefix);
485
486 if (str_len < prefix_len)
487 return 0;
488
489 return strncmp (str, prefix, prefix_len) == 0;
490 }
491
492 static int
493 edit_dwarf2_line (DSO *dso, rpmuint32_t off, char *comp_dir, int phase)
494 {
495 unsigned char *ptr = debug_sections[DEBUG_LINE].data, *dir;
496 unsigned char **dirt;
497 unsigned char *endsec = ptr + debug_sections[DEBUG_LINE].size;
498 unsigned char *endcu, *endprol;
499 unsigned char opcode_base;
500 rpmuint32_t value, dirt_cnt;
501 size_t comp_dir_len = strlen (comp_dir);
502 size_t abs_file_cnt = 0, abs_dir_cnt = 0;
503
504 if (phase != 0)
505 return 0;
506
507 ptr += off;
508
509 endcu = ptr + 4;
510 endcu += read_32 (ptr);
511 if (endcu == ptr + 0xffffffff)
512 {
513 error (0, 0, "%s: 64-bit DWARF not supported", dso->filename);
514 return 1;
515 }
516
517 if (endcu > endsec)
518 {
519 error (0, 0, "%s: .debug_line CU does not fit into section",
520 dso->filename);
521 return 1;
522 }
523
524 value = read_16 (ptr);
525 if (value != 2 && value != 3 && value != 4)
526 {
527 error (0, 0, "%s: DWARF version %d unhandled", dso->filename,
528 value);
529 return 1;
530 }
531
532 endprol = ptr + 4;
533 endprol += read_32 (ptr);
534 if (endprol > endcu)
535 {
536 error (0, 0, "%s: .debug_line CU prologue does not fit into CU",
537 dso->filename);
538 return 1;
539 }
540
541 opcode_base = ptr[4 + (value >= 4)];
542 ptr = dir = ptr + 4 + (value >= 4) + opcode_base;
543
544 /* dir table: */
545 value = 1;
546 while (*ptr != 0)
547 {
548 ptr = (unsigned char *) strchr ((char *)ptr, 0) + 1;
549 ++value;
550 }
551
552 dirt = (unsigned char **) alloca (value * sizeof (unsigned char *));
553 dirt[0] = (unsigned char *) ".";
554 dirt_cnt = 1;
555 ptr = dir;
556 while (*ptr != 0)
557 {
558 dirt[dirt_cnt++] = ptr;
559 ptr = (unsigned char *) strchr ((char *)ptr, 0) + 1;
560 }
561 ptr++;
562
563 /* file table: */
564 while (*ptr != 0)
565 {
566 char *s, *file;
567 size_t file_len, dir_len;
568
569 file = (char *) ptr;
570 ptr = (unsigned char *) strchr ((char *)ptr, 0) + 1;
571 value = read_uleb128 (ptr);
572
573 if (value >= dirt_cnt)
574 {
575 error (0, 0, "%s: Wrong directory table index %u",
576 dso->filename, value);
577 return 1;
578 }
579 file_len = strlen (file);
580 dir_len = strlen ((char *)dirt[value]);
581 s = malloc (comp_dir_len + 1 + file_len + 1 + dir_len + 1);
582 if (s == NULL)
583 {
584 error (0, ENOMEM, "%s: Reading file table", dso->filename);
585 return 1;
586 }
587 if (*file == '/')
588 {
589 memcpy (s, file, file_len + 1);
590 if (dest_dir && has_prefix (file, base_dir))
591 ++abs_file_cnt;
592 }
593 else if (*dirt[value] == '/')
594 {
595 memcpy (s, dirt[value], dir_len);
596 s[dir_len] = '/';
597 memcpy (s + dir_len + 1, file, file_len + 1);
598 }
599 else
600 {
601 char *p = s;
602 if (comp_dir_len != 0)
603 {
604 memcpy (s, comp_dir, comp_dir_len);
605 s[comp_dir_len] = '/';
606 p += comp_dir_len + 1;
607 }
608 memcpy (p, dirt[value], dir_len);
609 p[dir_len] = '/';
610 memcpy (p + dir_len + 1, file, file_len + 1);
611 }
612 canonicalize_path (s, s);
613 if (list_file_fd != -1)
614 {
615 char *p = NULL;
616 if (base_dir == NULL)
617 p = s;
618 else if (has_prefix (s, base_dir))
619 p = s + strlen (base_dir);
620 else if (has_prefix (s, dest_dir))
621 p = s + strlen (dest_dir);
622
623 if (p)
624 {
625 size_t size = strlen (p) + 1;
626 while (size > 0)
627 {
628 ssize_t ret = write (list_file_fd, p, size);
629 if (ret == -1)
630 break;
631 size -= ret;
632 p += ret;
633 }
634 }
635 }
636
637 free (s);
638
639 read_uleb128 (ptr);
640 read_uleb128 (ptr);
641 }
642 ++ptr;
643
644 if (dest_dir)
645 {
646 unsigned char *srcptr, *buf = NULL;
647 size_t base_len = strlen (base_dir);
648 size_t dest_len = strlen (dest_dir);
649 size_t shrank = 0;
650
651 if (dest_len == base_len)
652 abs_file_cnt = 0;
653 if (abs_file_cnt)
654 {
655 srcptr = buf = malloc (ptr - dir);
656 memcpy (srcptr, dir, ptr - dir);
657 ptr = dir;
658 }
659 else
660 ptr = srcptr = dir;
661 while (*srcptr != 0)
662 {
663 size_t len = strlen ((char *)srcptr) + 1;
664 const unsigned char *readptr = srcptr;
665
666 if (*srcptr == '/' && has_prefix ((char *)srcptr, base_dir))
667 {
668 if (dest_len < base_len)
669 ++abs_dir_cnt;
670 memcpy (ptr, dest_dir, dest_len);
671 ptr += dest_len;
672 readptr += base_len;
673 }
674 srcptr += len;
675
676 shrank += srcptr - readptr;
677 canonicalize_path ((char *)readptr, (char *)ptr);
678 len = strlen ((char *)ptr) + 1;
679 shrank -= len;
680 ptr += len;
681
682 elf_flagdata (debug_sections[DEBUG_STR].elf_data,
683 ELF_C_SET, ELF_F_DIRTY);
684 }
685
686 if (shrank > 0)
687 {
688 if (--shrank == 0)
689 error (EXIT_FAILURE, 0,
690 "canonicalization unexpectedly shrank by one character");
691 else
692 {
693 memset (ptr, 'X', shrank);
694 ptr += shrank;
695 *ptr++ = '\0';
696 }
697 }
698
699 if (abs_dir_cnt + abs_file_cnt != 0)
700 {
701 size_t len = (abs_dir_cnt + abs_file_cnt) * (base_len - dest_len);
702
703 if (len == 1)
704 error (EXIT_FAILURE, 0, "-b arg has to be either the same length as -d arg, or more than 1 char shorter");
705 memset (ptr, 'X', len - 1);
706 ptr += len - 1;
707 *ptr++ = '\0';
708 }
709 *ptr++ = '\0';
710 ++srcptr;
711
712 while (*srcptr != 0)
713 {
714 size_t len = strlen ((char *)srcptr) + 1;
715
716 if (*srcptr == '/' && has_prefix ((char *)srcptr, base_dir))
717 {
718 memcpy (ptr, dest_dir, dest_len);
719 if (dest_len < base_len)
720 {
721 memmove (ptr + dest_len, srcptr + base_len,
722 len - base_len);
723 ptr += dest_len - base_len;
724 }
725 elf_flagdata (debug_sections[DEBUG_STR].elf_data,
726 ELF_C_SET, ELF_F_DIRTY);
727 }
728 else if (ptr != srcptr)
729 memmove (ptr, srcptr, len);
730 srcptr += len;
731 ptr += len;
732 dir = srcptr;
733 read_uleb128 (srcptr);
734 read_uleb128 (srcptr);
735 read_uleb128 (srcptr);
736 if (ptr != dir)
737 memmove (ptr, dir, srcptr - dir);
738 ptr += srcptr - dir;
739 }
740 *ptr = '\0';
741 free (buf);
742 }
743 return 0;
744 }
745
746
747
748 static unsigned char *
749 edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase)
750 {
751 int i;
752 rpmuint32_t list_offs;
753 int found_list_offs;
754 char *comp_dir;
755
756 comp_dir = NULL;
757 list_offs = 0;
758 found_list_offs = 0;
759 for (i = 0; i < t->nattr; ++i)
760 {
761 rpmuint32_t form = t->attr[i].form;
762 size_t len = 0;
763 size_t base_len, dest_len;
764
765
766 while (1)
767 {
768 if (t->attr[i].attr == DW_AT_stmt_list)
769 {
770 if (form == DW_FORM_data4
771 || form == DW_FORM_sec_offset)
772 {
773 list_offs = do_read_32_relocated (ptr);
774 found_list_offs = 1;
775 }
776 }
777
778 if (t->attr[i].attr == DW_AT_comp_dir)
779 {
780 if ( form == DW_FORM_string )
781 {
782 free (comp_dir);
783 comp_dir = strdup ((char *)ptr);
784
785 if (phase == 1 && dest_dir && has_prefix ((char *)ptr, base_dir))
786 {
787 base_len = strlen (base_dir);
788 dest_len = strlen (dest_dir);
789
790 memcpy (ptr, dest_dir, dest_len);
791 if (dest_len < base_len)
792 {
793 memset(ptr + dest_len, '/',
794 base_len - dest_len);
795
796 }
797 elf_flagdata (debug_sections[DEBUG_INFO].elf_data,
798 ELF_C_SET, ELF_F_DIRTY);
799 }
800 }
801
802 else if (form == DW_FORM_strp &&
803 debug_sections[DEBUG_STR].data)
804 {
805 char *dir;
806
807 dir = (char *) debug_sections[DEBUG_STR].data
808 + do_read_32_relocated (ptr);
809
810 free (comp_dir);
811 comp_dir = strdup (dir);
812
813 if (phase == 1 && dest_dir && has_prefix (dir, base_dir))
814 {
815 base_len = strlen (base_dir);
816 dest_len = strlen (dest_dir);
817
818 memcpy (dir, dest_dir, dest_len);
819 if (dest_len < base_len)
820 {
821 memmove (dir + dest_len, dir + base_len,
822 strlen (dir + base_len) + 1);
823 }
824 elf_flagdata (debug_sections[DEBUG_STR].elf_data,
825 ELF_C_SET, ELF_F_DIRTY);
826 }
827 }
828 }
829 else if ((t->tag == DW_TAG_compile_unit
830 || t->tag == DW_TAG_partial_unit)
831 && t->attr[i].attr == DW_AT_name
832 && form == DW_FORM_strp
833 && debug_sections[DEBUG_STR].data)
834 {
835 char *name;
836
837 name = (char *) debug_sections[DEBUG_STR].data
838 + do_read_32_relocated (ptr);
839 if (*name == '/' && comp_dir == NULL)
840 {
841 char *enddir = strrchr (name, '/');
842
843 if (enddir != name)
844 {
845 comp_dir = malloc (enddir - name + 1);
846 memcpy (comp_dir, name, enddir - name);
847 comp_dir [enddir - name] = '\0';
848 }
849 else
850 comp_dir = strdup ("/");
851 }
852
853 if (phase == 1 && dest_dir && has_prefix (name, base_dir))
854 {
855 base_len = strlen (base_dir);
856 dest_len = strlen (dest_dir);
857
858 memcpy (name, dest_dir, dest_len);
859 if (dest_len < base_len)
860 {
861 memmove (name + dest_len, name + base_len,
862 strlen (name + base_len) + 1);
863 }
864 elf_flagdata (debug_sections[DEBUG_STR].elf_data,
865 ELF_C_SET, ELF_F_DIRTY);
866 }
867 }
868
869 switch (form)
870 {
871 case DW_FORM_ref_addr:
872 if (cu_version == 2)
873 ptr += ptr_size;
874 else
875 ptr += 4;
876 break;
877 case DW_FORM_flag_present:
878 break;
879 case DW_FORM_addr:
880 ptr += ptr_size;
881 break;
882 case DW_FORM_ref1:
883 case DW_FORM_flag:
884 case DW_FORM_data1:
885 ++ptr;
886 break;
887 case DW_FORM_ref2:
888 case DW_FORM_data2:
889 ptr += 2;
890 break;
891 case DW_FORM_ref4:
892 case DW_FORM_data4:
893 case DW_FORM_sec_offset:
894 ptr += 4;
895 break;
896 case DW_FORM_ref8:
897 case DW_FORM_data8:
898 case DW_FORM_ref_sig8:
899 ptr += 8;
900 break;
901 case DW_FORM_sdata:
902 case DW_FORM_ref_udata:
903 case DW_FORM_udata:
904 read_uleb128 (ptr);
905 break;
906 case DW_FORM_strp:
907 ptr += 4;
908 break;
909 case DW_FORM_string:
910 ptr = (unsigned char *) strchr ((char *)ptr, '\0') + 1;
911 break;
912 case DW_FORM_indirect:
913 form = read_uleb128 (ptr);
914 continue;
915 case DW_FORM_block1:
916 len = *ptr++;
917 break;
918 case DW_FORM_block2:
919 len = read_16 (ptr);
920 form = DW_FORM_block1;
921 break;
922 case DW_FORM_block4:
923 len = read_32 (ptr);
924 form = DW_FORM_block1;
925 break;
926 case DW_FORM_block:
927 case DW_FORM_exprloc:
928 len = read_uleb128 (ptr);
929 form = DW_FORM_block1;
930 assert (len < UINT_MAX);
931 break;
932 default:
933 error (0, 0, "%s: Unknown DWARF DW_FORM_%d", dso->filename,
934 form);
935 return NULL;
936 }
937
938 if (form == DW_FORM_block1)
939 ptr += len;
940
941 break;
942 }
943 }
944
945 /* Ensure the CU current directory will exist even if only empty. Source
946 filenames possibly located in its parent directories refer relatively to
947 it and the debugger (GDB) cannot safely optimize out the missing
948 CU current dir subdirectories. */
949 if (comp_dir && list_file_fd != -1)
950 {
951 char *p;
952 size_t size;
953
954 if (base_dir && has_prefix (comp_dir, base_dir))
955 p = comp_dir + strlen (base_dir);
956 else if (dest_dir && has_prefix (comp_dir, dest_dir))
957 p = comp_dir + strlen (dest_dir);
958 else
959 p = comp_dir;
960
961 size = strlen (p) + 1;
962 while (size > 0)
963 {
964 ssize_t ret = write (list_file_fd, p, size);
965 if (ret == -1)
966 break;
967 size -= ret;
968 p += ret;
969 }
970 }
971
972 if (found_list_offs && comp_dir)
973 edit_dwarf2_line (dso, list_offs, comp_dir, phase);
974
975 free (comp_dir);
976
977 return ptr;
978 }
979
980 static int
981 rel_cmp (const void *a, const void *b)
982 {
983 REL *rela = (REL *) a, *relb = (REL *) b;
984
985 if (rela->ptr < relb->ptr)
986 return -1;
987
988 if (rela->ptr > relb->ptr)
989 return 1;
990
991 return 0;
992 }
993
994 static int
995 edit_dwarf2 (DSO *dso)
996 {
997 Elf_Data *data;
998 Elf_Scn *scn;
999 int i, j;
1000
1001 for (i = 0; debug_sections[i].name; ++i)
1002 {
1003 debug_sections[i].data = NULL;
1004 debug_sections[i].size = 0;
1005 debug_sections[i].sec = 0;
1006 debug_sections[i].relsec = 0;
1007 }
1008 ptr_size = 0;
1009
1010 for (i = 1; i < dso->ehdr.e_shnum; ++i)
1011 if (! (dso->shdr[i].sh_flags & (SHF_ALLOC | SHF_WRITE | SHF_EXECINSTR))
1012 && dso->shdr[i].sh_size)
1013 {
1014 const char *name = strptr (dso, dso->ehdr.e_shstrndx,
1015 dso->shdr[i].sh_name);
1016
1017 if (strncmp (name, ".debug_", sizeof (".debug_") - 1) == 0)
1018 {
1019 for (j = 0; debug_sections[j].name; ++j)
1020 if (strcmp (name, debug_sections[j].name) == 0)
1021 {
1022 if (debug_sections[j].data)
1023 {
1024 error (0, 0, "%s: Found two copies of %s section",
1025 dso->filename, name);
1026 return 1;
1027 }
1028
1029 scn = dso->scn[i];
1030 data = elf_rawdata (scn, NULL);
1031 assert (data != NULL && data->d_buf != NULL);
1032 assert (elf_rawdata (scn, data) == NULL);
1033 assert (data->d_off == 0);
1034 assert (data->d_size == dso->shdr[i].sh_size);
1035 debug_sections[j].data = data->d_buf;
1036 debug_sections[j].elf_data = data;
1037 debug_sections[j].size = data->d_size;
1038 debug_sections[j].sec = i;
1039 break;
1040 }
1041
1042 if (debug_sections[j].name == NULL)
1043 {
1044 error (0, 0, "%s: Unknown debugging section %s",
1045 dso->filename, name);
1046 }
1047 }
1048 else if (dso->ehdr.e_type == ET_REL
1049 && ((dso->shdr[i].sh_type == SHT_REL
1050 && strncmp (name, ".rel.debug_",
1051 sizeof (".rel.debug_") - 1) == 0)
1052 || (dso->shdr[i].sh_type == SHT_RELA
1053 && strncmp (name, ".rela.debug_",
1054 sizeof (".rela.debug_") - 1) == 0)))
1055 {
1056 for (j = 0; debug_sections[j].name; ++j)
1057 if (strcmp (name + sizeof (".rel") - 1
1058 + (dso->shdr[i].sh_type == SHT_RELA),
1059 debug_sections[j].name) == 0)
1060 {
1061 debug_sections[j].relsec = i;
1062 break;
1063 }
1064 }
1065 }
1066
1067 if (dso->ehdr.e_ident[EI_DATA] == ELFDATA2LSB)
1068 {
1069 do_read_16 = buf_read_ule16;
1070 do_read_32 = buf_read_ule32;
1071 write_32 = dwarf2_write_le32;
1072 }
1073 else if (dso->ehdr.e_ident[EI_DATA] == ELFDATA2MSB)
1074 {
1075 do_read_16 = buf_read_ube16;
1076 do_read_32 = buf_read_ube32;
1077 write_32 = dwarf2_write_be32;
1078 }
1079 else
1080 {
1081 error (0, 0, "%s: Wrong ELF data enconding", dso->filename);
1082 return 1;
1083 }
1084
1085 if (debug_sections[DEBUG_INFO].data != NULL)
1086 {
1087 unsigned char *ptr, *endcu, *endsec;
1088 rpmuint32_t value;
1089 htab_t abbrev;
1090 struct abbrev_tag tag, *t;
1091 int phase;
1092 REL *relbuf = NULL;
1093
1094 if (debug_sections[DEBUG_INFO].relsec)
1095 {
1096 int ndx, maxndx;
1097 GElf_Rel rel;
1098 GElf_Rela rela;
1099 GElf_Sym sym;
1100 GElf_Addr base = dso->shdr[debug_sections[DEBUG_INFO].sec].sh_addr;
1101 Elf_Data *symdata = NULL;
1102 int rtype;
1103
1104 i = debug_sections[DEBUG_INFO].relsec;
1105 scn = dso->scn[i];
1106 data = elf_getdata (scn, NULL);
1107 assert (data != NULL && data->d_buf != NULL);
1108 assert (elf_getdata (scn, data) == NULL);
1109 assert (data->d_off == 0);
1110 assert (data->d_size == dso->shdr[i].sh_size);
1111 maxndx = dso->shdr[i].sh_size / dso->shdr[i].sh_entsize;
1112 relbuf = malloc (maxndx * sizeof (REL));
1113 reltype = dso->shdr[i].sh_type;
1114 if (relbuf == NULL)
1115 error (1, errno, "%s: Could not allocate memory", dso->filename);
1116
1117 symdata = elf_getdata (dso->scn[dso->shdr[i].sh_link], NULL);
1118 assert (symdata != NULL && symdata->d_buf != NULL);
1119 assert (elf_getdata (dso->scn[dso->shdr[i].sh_link], symdata)
1120 == NULL);
1121 assert (symdata->d_off == 0);
1122 assert (symdata->d_size
1123 == dso->shdr[dso->shdr[i].sh_link].sh_size);
1124
1125 for (ndx = 0, relend = relbuf; ndx < maxndx; ++ndx)
1126 {
1127 if (dso->shdr[i].sh_type == SHT_REL)
1128 {
1129 gelf_getrel (data, ndx, &rel);
1130 rela.r_offset = rel.r_offset;
1131 rela.r_info = rel.r_info;
1132 rela.r_addend = 0;
1133 }
1134 else
1135 gelf_getrela (data, ndx, &rela);
1136 gelf_getsym (symdata, ELF64_R_SYM (rela.r_info), &sym);
1137 /* Relocations against section symbols are uninteresting
1138 in REL. */
1139 if (dso->shdr[i].sh_type == SHT_REL && sym.st_value == 0)
1140 continue;
1141 /* Only consider relocations against .debug_str, .debug_line
1142 and .debug_abbrev. */
1143 if (sym.st_shndx != debug_sections[DEBUG_STR].sec
1144 && sym.st_shndx != debug_sections[DEBUG_LINE].sec
1145 && sym.st_shndx != debug_sections[DEBUG_ABBREV].sec)
1146 continue;
1147 rela.r_addend += sym.st_value;
1148 rtype = ELF64_R_TYPE (rela.r_info);
1149 switch (dso->ehdr.e_machine)
1150 {
1151 case EM_SPARC:
1152 case EM_SPARC32PLUS:
1153 case EM_SPARCV9:
1154 if (rtype != R_SPARC_32 && rtype != R_SPARC_UA32)
1155 goto fail;
1156 break;
1157 case EM_386:
1158 if (rtype != R_386_32)
1159 goto fail;
1160 break;
1161 case EM_PPC:
1162 case EM_PPC64:
1163 if (rtype != R_PPC_ADDR32 && rtype != R_PPC_UADDR32)
1164 goto fail;
1165 break;
1166 case EM_S390:
1167 if (rtype != R_390_32)
1168 goto fail;
1169 break;
1170 case EM_IA_64:
1171 if (rtype != R_IA64_SECREL32LSB)
1172 goto fail;
1173 break;
1174 case EM_X86_64:
1175 if (rtype != R_X86_64_32)
1176 goto fail;
1177 break;
1178 case EM_ALPHA:
1179 if (rtype != R_ALPHA_REFLONG)
1180 goto fail;
1181 break;
1182 default:
1183 fail:
1184 error (1, 0, "%s: Unhandled relocation %d in .debug_info section",
1185 dso->filename, rtype);
1186 }
1187 relend->ptr = debug_sections[DEBUG_INFO].data
1188 + (rela.r_offset - base);
1189 relend->addend = rela.r_addend;
1190 ++relend;
1191 }
1192 if (relbuf == relend)
1193 {
1194 free (relbuf);
1195 relbuf = NULL;
1196 relend = NULL;
1197 }
1198 else
1199 qsort (relbuf, relend - relbuf, sizeof (REL), rel_cmp);
1200 }
1201
1202 for (phase = 0; phase < 2; phase++)
1203 {
1204 ptr = debug_sections[DEBUG_INFO].data;
1205 relptr = relbuf;
1206 endsec = ptr + debug_sections[DEBUG_INFO].size;
1207 while (ptr < endsec)
1208 {
1209 if (ptr + 11 > endsec)
1210 {
1211 error (0, 0, "%s: .debug_info CU header too small",
1212 dso->filename);
1213 return 1;
1214 }
1215
1216 endcu = ptr + 4;
1217 endcu += read_32 (ptr);
1218 if (endcu == ptr + 0xffffffff)
1219 {
1220 error (0, 0, "%s: 64-bit DWARF not supported", dso->filename);
1221 return 1;
1222 }
1223
1224 if (endcu > endsec)
1225 {
1226 error (0, 0, "%s: .debug_info too small", dso->filename);
1227 return 1;
1228 }
1229
1230 cu_version = read_16 (ptr);
1231 if (cu_version != 2 && cu_version != 3 && cu_version != 4)
1232 {
1233 error (0, 0, "%s: DWARF version %d unhandled", dso->filename,
1234 cu_version);
1235 return 1;
1236 }
1237
1238 value = read_32_relocated (ptr);
1239 if (value >= debug_sections[DEBUG_ABBREV].size)
1240 {
1241 if (debug_sections[DEBUG_ABBREV].data == NULL)
1242 error (0, 0, "%s: .debug_abbrev not present", dso->filename);
1243 else
1244 error (0, 0, "%s: DWARF CU abbrev offset too large",
1245 dso->filename);
1246 return 1;
1247 }
1248
1249 if (ptr_size == 0)
1250 {
1251 ptr_size = read_1 (ptr);
1252 if (ptr_size != 4 && ptr_size != 8)
1253 {
1254 error (0, 0, "%s: Invalid DWARF pointer size %d",
1255 dso->filename, ptr_size);
1256 return 1;
1257 }
1258 }
1259 else if (read_1 (ptr) != ptr_size)
1260 {
1261 error (0, 0, "%s: DWARF pointer size differs between CUs",
1262 dso->filename);
1263 return 1;
1264 }
1265
1266 abbrev = read_abbrev (dso,
1267 debug_sections[DEBUG_ABBREV].data + value);
1268 if (abbrev == NULL)
1269 return 1;
1270
1271 while (ptr < endcu)
1272 {
1273 tag.entry = read_uleb128 (ptr);
1274 if (tag.entry == 0)
1275 continue;
1276 t = htab_find_with_hash (abbrev, &tag, tag.entry);
1277 if (t == NULL)
1278 {
1279 error (0, 0, "%s: Could not find DWARF abbreviation %d",
1280 dso->filename, tag.entry);
1281 htab_delete (abbrev);
1282 return 1;
1283 }
1284
1285 ptr = edit_attributes (dso, ptr, t, phase);
1286 if (ptr == NULL)
1287 break;
1288 }
1289
1290 htab_delete (abbrev);
1291 }
1292 }
1293 free (relbuf);
1294 }
1295
1296 return 0;
1297 }
1298
1299 static struct poptOption optionsTable[] = {
1300 { "base-dir", 'b', POPT_ARG_STRING, &base_dir, 0,
1301 "base build directory of objects", NULL },
1302 { "dest-dir", 'd', POPT_ARG_STRING, &dest_dir, 0,
1303 "directory to rewrite base-dir into", NULL },
1304 { "list-file", 'l', POPT_ARG_STRING, &list_file, 0,
1305 "file where to put list of source and header file names", NULL },
1306 { "build-id", 'i', POPT_ARG_NONE, &do_build_id, 0,
1307 "recompute build ID note and print ID on stdout", NULL },
1308 POPT_AUTOHELP
1309 { NULL, 0, 0, NULL, 0, NULL, NULL }
1310 };
1311
1312 static DSO *
1313 fdopen_dso (int fd, const char *name)
1314 {
1315 Elf *elf = NULL;
1316 GElf_Ehdr ehdr;
1317 int i;
1318 DSO *dso = NULL;
1319
1320 elf = elf_begin (fd, ELF_C_RDWR_MMAP, NULL);
1321 if (elf == NULL)
1322 {
1323 error (0, 0, "cannot open ELF file: %s", elf_errmsg (-1));
1324 goto error_out;
1325 }
1326
1327 if (elf_kind (elf) != ELF_K_ELF)
1328 {
1329 error (0, 0, "\"%s\" is not an ELF file", name);
1330 goto error_out;
1331 }
1332
1333 if (gelf_getehdr (elf, &ehdr) == NULL)
1334 {
1335 error (0, 0, "cannot get the ELF header: %s",
1336 elf_errmsg (-1));
1337 goto error_out;
1338 }
1339
1340 if (ehdr.e_type != ET_DYN && ehdr.e_type != ET_EXEC && ehdr.e_type != ET_REL)
1341 {
1342 error (0, 0, "\"%s\" is not a shared library", name);
1343 goto error_out;
1344 }
1345
1346 /* Allocate DSO structure. Leave place for additional 20 new section
1347 headers. */
1348 dso = (DSO *)
1349 malloc (sizeof(DSO) + (ehdr.e_shnum + 20) * sizeof(GElf_Shdr)
1350 + (ehdr.e_shnum + 20) * sizeof(Elf_Scn *));
1351 if (!dso)
1352 {
1353 error (0, ENOMEM, "Could not open DSO");
1354 goto error_out;
1355 }
1356
1357 elf_flagelf (elf, ELF_C_SET, ELF_F_LAYOUT);
1358
1359 memset (dso, 0, sizeof(DSO));
1360 dso->elf = elf;
1361 dso->ehdr = ehdr;
1362 dso->scn = (Elf_Scn **) &dso->shdr[ehdr.e_shnum + 20];
1363
1364 for (i = 0; i < ehdr.e_shnum; ++i)
1365 {
1366 dso->scn[i] = elf_getscn (elf, i);
1367 gelf_getshdr (dso->scn[i], dso->shdr + i);
1368 }
1369
1370 dso->filename = (const char *) strdup (name);
1371 return dso;
1372
1373 error_out:
1374 if (dso)
1375 {
1376 free ((char *) dso->filename);
1377 free (dso);
1378 }
1379 if (elf)
1380 elf_end (elf);
1381 if (fd != -1)
1382 close (fd);
1383 return NULL;
1384 }
1385
1386 /* Compute a fresh build ID bit-string from the editted file contents. */
1387 static void
1388 handle_build_id (DSO *dso, Elf_Data *build_id,
1389 size_t build_id_offset, size_t build_id_size)
1390 {
1391 hashFunctionContext ctx;
1392 const hashFunction *hf = NULL;
1393 int i = hashFunctionCount ();
1394
1395 while (i-- > 0)
1396 {
1397 hf = hashFunctionGet (i);
1398 if (hf != NULL && hf->digestsize == build_id_size)
1399 break;
1400 }
1401 if (hf == NULL)
1402 {
1403 fprintf (stderr, "Cannot handle %Zu-byte build ID\n", build_id_size);
1404 exit (1);
1405 }
1406
1407 if (elf_update (dso->elf, ELF_C_NULL) < 0)
1408 {
1409 fprintf (stderr, "Failed to update file: %s\n",
1410 elf_errmsg (elf_errno ()));
1411 exit (1);
1412 }
1413
1414 /* Clear the old bits so they do not affect the new hash. */
1415 memset ((char *) build_id->d_buf + build_id_offset, 0, build_id_size);
1416
1417 hashFunctionContextInit (&ctx, hf);
1418
1419 /* Slurp the relevant header bits and section contents and feed them
1420 into the hash function. The only bits we ignore are the offset
1421 fields in ehdr and shdrs, since the semantically identical ELF file
1422 could be written differently if it doesn't change the phdr layout.
1423 We always use the GElf (i.e. Elf64) formats for the bits to hash
1424 since it is convenient. It doesn't matter whether this is an Elf32
1425 or Elf64 object, only that we are consistent in what bits feed the
1426 hash so it comes out the same for the same file contents. */
1427 {
1428 auto inline void process (const void *data, size_t size);
1429 auto inline void process (const void *data, size_t size)
1430 {
1431 memchunk chunk = { .data = (void *) data, .size = size };
1432 hashFunctionContextUpdateMC (&ctx, &chunk);
1433 }
1434 union
1435 {
1436 GElf_Ehdr ehdr;
1437 GElf_Phdr phdr;
1438 GElf_Shdr shdr;
1439 } u;
1440 Elf_Data x = { .d_version = EV_CURRENT, .d_buf = &u };
1441
1442 x.d_type = ELF_T_EHDR;
1443 x.d_size = sizeof u.ehdr;
1444 u.ehdr = dso->ehdr;
1445 u.ehdr.e_phoff = u.ehdr.e_shoff = 0;
1446 if (elf64_xlatetom (&x, &x, dso->ehdr.e_ident[EI_DATA]) == NULL)
1447 {
1448 bad:
1449 fprintf (stderr, "Failed to compute header checksum: %s\n",
1450 elf_errmsg (elf_errno ()));
1451 exit (1);
1452 }
1453
1454 x.d_type = ELF_T_PHDR;
1455 x.d_size = sizeof u.phdr;
1456 for (i = 0; i < dso->ehdr.e_phnum; ++i)
1457 {
1458 if (gelf_getphdr (dso->elf, i, &u.phdr) == NULL)
1459 goto bad;
1460 if (elf64_xlatetom (&x, &x, dso->ehdr.e_ident[EI_DATA]) == NULL)
1461 goto bad;
1462 process (x.d_buf, x.d_size);
1463 }
1464
1465 x.d_type = ELF_T_SHDR;
1466 x.d_size = sizeof u.shdr;
1467 for (i = 0; i < dso->ehdr.e_shnum; ++i)
1468 if (dso->scn[i] != NULL)
1469 {
1470 u.shdr = dso->shdr[i];
1471 u.shdr.sh_offset = 0;
1472 if (elf64_xlatetom (&x, &x, dso->ehdr.e_ident[EI_DATA]) == NULL)
1473 goto bad;
1474 process (x.d_buf, x.d_size);
1475
1476 if (u.shdr.sh_type != SHT_NOBITS)
1477 {
1478 Elf_Data *d = elf_rawdata (dso->scn[i], NULL);
1479 if (d == NULL)
1480 goto bad;
1481 process (d->d_buf, d->d_size);
1482 }
1483 }
1484 }
1485
1486 hashFunctionContextDigest (&ctx, (byte *) build_id->d_buf + build_id_offset);
1487 hashFunctionContextFree (&ctx);
1488
1489 elf_flagdata (build_id, ELF_C_SET, ELF_F_DIRTY);
1490
1491 /* Now format the build ID bits in hex to print out. */
1492 {
1493 const rpmuint8_t * id = (rpmuint8_t *)build_id->d_buf + build_id_offset;
1494 char hex[build_id_size * 2 + 1];
1495 int n = snprintf (hex, 3, "%02" PRIx8, id[0]);
1496 assert (n == 2);
1497 for (i = 1; i < (int)build_id_size; ++i)
1498 {
1499 n = snprintf (&hex[i * 2], 3, "%02" PRIx8, id[i]);
1500 assert (n == 2);
1501 }
1502 puts (hex);
1503 }
1504 }
1505
1506 int
1507 main (int argc, char *argv[])
1508 {
1509 DSO *dso;
1510 int fd, i;
1511 const char *file;
1512 poptContext optCon; /* context for parsing command-line options */
1513 int nextopt;
1514 const char **args;
1515 struct stat stat_buf;
1516 char *p;
1517 Elf_Data *build_id = NULL;
1518 size_t build_id_offset = 0, build_id_size = 0;
1519
1520 optCon = poptGetContext("debugedit", argc, (const char **)argv, optionsTable, 0);
1521
1522 while ((nextopt = poptGetNextOpt (optCon)) > 0 || nextopt == POPT_ERROR_BADOPT)
1523 /* do nothing */ ;
1524
1525 if (nextopt != -1)
1526 {
1527 fprintf (stderr, "Error on option %s: %s.\nRun '%s --help' to see a full list of available command line options.\n",
1528 poptBadOption (optCon, 0),
1529 poptStrerror (nextopt),
1530 argv[0]);
1531 exit (1);
1532 }
1533
1534 args = poptGetArgs (optCon);
1535 if (args == NULL || args[0] == NULL || args[1] != NULL)
1536 {
1537 poptPrintHelp(optCon, stdout, 0);
1538 exit (1);
1539 }
1540
1541 if (dest_dir != NULL)
1542 {
1543 if (base_dir == NULL)
1544 {
1545 fprintf (stderr, "You must specify a base dir if you specify a dest dir\n");
1546 exit (1);
1547 }
1548 if (strlen (dest_dir) > strlen (base_dir))
1549 {
1550 fprintf (stderr, "Only dest dir longer than base dir not supported\n");
1551 exit (1);
1552 }
1553 }
1554
1555 /* Make sure there are trailing slashes in dirs */
1556 if (base_dir != NULL && base_dir[strlen (base_dir)-1] != '/')
1557 {
1558 p = malloc (strlen (base_dir) + 2);
1559 strcpy (p, base_dir);
1560 strcat (p, "/");
1561 free (base_dir);
1562 base_dir = p;
1563 }
1564 if (dest_dir != NULL && dest_dir[strlen (dest_dir)-1] != '/')
1565 {
1566 p = malloc (strlen (dest_dir) + 2);
1567 strcpy (p, dest_dir);
1568 strcat (p, "/");
1569 free (dest_dir);
1570 dest_dir = p;
1571 }
1572
1573 if (list_file != NULL)
1574 {
1575 list_file_fd = open (list_file, O_WRONLY|O_CREAT|O_APPEND, 0644);
1576 }
1577
1578 file = args[0];
1579
1580 if (elf_version(EV_CURRENT) == EV_NONE)
1581 {
1582 fprintf (stderr, "library out of date\n");
1583 exit (1);
1584 }
1585
1586 if (stat(file, &stat_buf) < 0)
1587 {
1588 fprintf (stderr, "Failed to open input file '%s': %s\n", file, strerror(errno));
1589 exit (1);
1590 }
1591
1592 /* Make sure we can read and write */
1593 chmod (file, stat_buf.st_mode | S_IRUSR | S_IWUSR);
1594
1595 fd = open (file, O_RDWR);
1596 if (fd < 0)
1597 {
1598 fprintf (stderr, "Failed to open input file '%s': %s\n", file, strerror(errno));
1599 exit (1);
1600 }
1601
1602 dso = fdopen_dso (fd, file);
1603 if (dso == NULL)
1604 exit (1);
1605
1606 for (i = 1; i < dso->ehdr.e_shnum; i++)
1607 {
1608 const char *name;
1609
1610 switch (dso->shdr[i].sh_type)
1611 {
1612 case SHT_PROGBITS:
1613 case SHT_MIPS_DWARF:
1614 name = strptr (dso, dso->ehdr.e_shstrndx, dso->shdr[i].sh_name);
1615 /* TODO: Handle stabs */
1616 #if 0
1617 if (strcmp (name, ".stab") == 0)
1618 edit_stabs (dso, i);
1619 #endif
1620 if (strcmp (name, ".debug_info") == 0)
1621 edit_dwarf2 (dso);
1622
1623 break;
1624 case SHT_NOTE:
1625 if (do_build_id
1626 && build_id == NULL && (dso->shdr[i].sh_flags & SHF_ALLOC))
1627 {
1628 /* Look for a build-ID note here. */
1629 Elf_Data *data = elf_rawdata (elf_getscn (dso->elf, i), NULL);
1630 Elf32_Nhdr nh;
1631 Elf_Data dst =
1632 {
1633 .d_version = EV_CURRENT, .d_type = ELF_T_NHDR,
1634 .d_buf = &nh, .d_size = sizeof nh
1635 };
1636 Elf_Data src = dst;
1637 src.d_buf = data->d_buf;
1638 assert (sizeof (Elf32_Nhdr) == sizeof (Elf64_Nhdr));
1639 while ((char *) data->d_buf + data->d_size -
1640 (char *) src.d_buf > (int) sizeof nh
1641 && elf32_xlatetom (&dst, &src, dso->ehdr.e_ident[EI_DATA]))
1642 {
1643 Elf32_Word len = sizeof nh + nh.n_namesz;
1644 len = (len + 3) & ~3;
1645
1646 if (nh.n_namesz == sizeof "GNU" && nh.n_type == 3
1647 && !memcmp ((char *) src.d_buf + sizeof nh, "GNU", sizeof "GNU"))
1648 {
1649 build_id = data;
1650 build_id_offset = (char *) src.d_buf + len -
1651 (char *) data->d_buf;
1652 build_id_size = nh.n_descsz;
1653 break;
1654 }
1655
1656 len += nh.n_descsz;
1657 len = (len + 3) & ~3;
1658 src.d_buf = (char *) src.d_buf + len;
1659 }
1660 }
1661 break;
1662 default:
1663 break;
1664 }
1665 }
1666
1667 if (do_build_id && build_id != NULL)
1668 handle_build_id (dso, build_id, build_id_offset, build_id_size);
1669
1670 if (elf_update (dso->elf, ELF_C_WRITE) < 0)
1671 {
1672 fprintf (stderr, "Failed to write file: %s\n", elf_errmsg (elf_errno()));
1673 exit (1);
1674 }
1675 if (elf_end (dso->elf) < 0)
1676 {
1677 fprintf (stderr, "elf_end failed: %s\n", elf_errmsg (elf_errno()));
1678 exit (1);
1679 }
1680 close (fd);
1681
1682 /* Restore old access rights */
1683 chmod (file, stat_buf.st_mode);
1684
1685 poptFreeContext (optCon);
1686
1687 return 0;
1688 }