1 /* Copyright (C) 2001, 2002, 2003, 2005, 2007, 2009, 2010, 2011 Red Hat, Inc.
2 Written by Alexander Larsson <alexl@redhat.com>, 2002
3 Based on code by Jakub Jelinek <jakub@redhat.com>, 2001.
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)
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.
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. */
21 /* Needed for libelf */
22 #define _FILE_OFFSET_BITS 64
34 #include <sys/types.h>
42 /* some defines taken from the dwarf standard */
44 #define DW_TAG_compile_unit 0x11
46 #define DW_AT_name 0x03
47 #define DW_AT_stmt_list 0x10
48 #define DW_AT_comp_dir 0x1b
50 #define DW_FORM_addr 0x01
51 #define DW_FORM_block2 0x03
52 #define DW_FORM_block4 0x04
53 #define DW_FORM_data2 0x05
54 #define DW_FORM_data4 0x06
55 #define DW_FORM_data8 0x07
56 #define DW_FORM_string 0x08
57 #define DW_FORM_block 0x09
58 #define DW_FORM_block1 0x0a
59 #define DW_FORM_data1 0x0b
60 #define DW_FORM_flag 0x0c
61 #define DW_FORM_sdata 0x0d
62 #define DW_FORM_strp 0x0e
63 #define DW_FORM_udata 0x0f
64 #define DW_FORM_ref_addr 0x10
65 #define DW_FORM_ref1 0x11
66 #define DW_FORM_ref2 0x12
67 #define DW_FORM_ref4 0x13
68 #define DW_FORM_ref8 0x14
69 #define DW_FORM_ref_udata 0x15
70 #define DW_FORM_indirect 0x16
72 #include <rpm/rpmio.h>
73 #include <rpm/rpmpgp.h>
74 #include "tools/hashtab.h"
76 #define DW_TAG_partial_unit 0x3c
77 #define DW_FORM_sec_offset 0x17
78 #define DW_FORM_exprloc 0x18
79 #define DW_FORM_flag_present 0x19
80 #define DW_FORM_ref_sig8 0x20
82 char *base_dir = NULL;
83 char *dest_dir = NULL;
84 char *list_file = NULL;
85 int list_file_fd = -1;
104 #define read_uleb128(ptr) ({ \
105 unsigned int ret = 0; \
111 ret |= (c & 0x7f) << shift; \
113 } while (c & 0x80); \
120 static uint16_t (*do_read_16) (unsigned char *ptr);
121 static uint32_t (*do_read_32) (unsigned char *ptr);
122 static void (*write_32) (unsigned char *ptr, GElf_Addr val);
125 static int cu_version;
127 static inline uint16_t
128 buf_read_ule16 (unsigned char *data)
130 return data[0] | (data[1] << 8);
133 static inline uint16_t
134 buf_read_ube16 (unsigned char *data)
136 return data[1] | (data[0] << 8);
139 static inline uint32_t
140 buf_read_ule32 (unsigned char *data)
142 return data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
145 static inline uint32_t
146 buf_read_ube32 (unsigned char *data)
148 return data[3] | (data[2] << 8) | (data[1] << 16) | (data[0] << 24);
152 strptr (DSO *dso, int sec, off_t offset)
158 if (offset >= 0 && (GElf_Addr) offset < dso->shdr[sec].sh_size)
161 while ((data = elf_rawdata (scn, data)) != NULL)
164 && offset >= data->d_off
165 && offset < data->d_off + (off_t)data->d_size)
166 return (const char *) data->d_buf + (offset - data->d_off);
174 #define read_1(ptr) *ptr++
176 #define read_16(ptr) ({ \
177 uint16_t ret = do_read_16 (ptr); \
182 #define read_32(ptr) ({ \
183 uint32_t ret = do_read_32 (ptr); \
188 REL *relptr, *relend;
191 #define do_read_32_relocated(ptr) ({ \
192 uint32_t dret = do_read_32 (ptr); \
195 while (relptr < relend && relptr->ptr < ptr) \
197 if (relptr < relend && relptr->ptr == ptr) \
199 if (reltype == SHT_REL) \
200 dret += relptr->addend; \
202 dret = relptr->addend; \
208 #define read_32_relocated(ptr) ({ \
209 uint32_t ret = do_read_32_relocated (ptr); \
215 dwarf2_write_le32 (unsigned char *p, GElf_Addr val)
217 uint32_t v = (uint32_t) val;
227 dwarf2_write_be32 (unsigned char *p, GElf_Addr val)
229 uint32_t v = (uint32_t) val;
247 #define DEBUG_ABBREV 1
249 #define DEBUG_ARANGES 3
250 #define DEBUG_PUBNAMES 4
251 #define DEBUG_PUBTYPES 5
252 #define DEBUG_MACINFO 6
255 #define DEBUG_FRAME 9
256 #define DEBUG_RANGES 10
257 #define DEBUG_TYPES 11
258 #define DEBUG_MACRO 12
259 { ".debug_info", NULL, NULL, 0, 0, 0 },
260 { ".debug_abbrev", NULL, NULL, 0, 0, 0 },
261 { ".debug_line", NULL, NULL, 0, 0, 0 },
262 { ".debug_aranges", NULL, NULL, 0, 0, 0 },
263 { ".debug_pubnames", NULL, NULL, 0, 0, 0 },
264 { ".debug_pubtypes", NULL, NULL, 0, 0, 0 },
265 { ".debug_macinfo", NULL, NULL, 0, 0, 0 },
266 { ".debug_loc", NULL, NULL, 0, 0, 0 },
267 { ".debug_str", NULL, NULL, 0, 0, 0 },
268 { ".debug_frame", NULL, NULL, 0, 0, 0 },
269 { ".debug_ranges", NULL, NULL, 0, 0, 0 },
270 { ".debug_types", NULL, NULL, 0, 0, 0 },
271 { ".debug_macro", NULL, NULL, 0, 0, 0 },
272 { NULL, NULL, NULL, 0, 0, 0 }
286 struct abbrev_attr attr[0];
290 abbrev_hash (const void *p)
292 struct abbrev_tag *t = (struct abbrev_tag *)p;
298 abbrev_eq (const void *p, const void *q)
300 struct abbrev_tag *t1 = (struct abbrev_tag *)p;
301 struct abbrev_tag *t2 = (struct abbrev_tag *)q;
303 return t1->entry == t2->entry;
313 read_abbrev (DSO *dso, unsigned char *ptr)
315 htab_t h = htab_try_create (50, abbrev_hash, abbrev_eq, abbrev_del);
316 unsigned int attr, form;
317 struct abbrev_tag *t;
324 error (0, ENOMEM, "%s: Could not read .debug_abbrev", dso->filename);
330 while ((attr = read_uleb128 (ptr)) != 0)
333 t = malloc (sizeof (*t) + size * sizeof (struct abbrev_attr));
338 slot = htab_find_slot (h, t, INSERT);
346 error (0, 0, "%s: Duplicate DWARF abbreviation %d", dso->filename,
352 t->tag = read_uleb128 (ptr);
353 ++ptr; /* skip children flag. */
354 while ((attr = read_uleb128 (ptr)) != 0)
356 if (t->nattr == size)
359 t = realloc (t, sizeof (*t) + size * sizeof (struct abbrev_attr));
363 form = read_uleb128 (ptr);
365 || (form > DW_FORM_flag_present && form != DW_FORM_ref_sig8))
367 error (0, 0, "%s: Unknown DWARF DW_FORM_%d", dso->filename, form);
372 t->attr[t->nattr].attr = attr;
373 t->attr[t->nattr++].form = form;
375 if (read_uleb128 (ptr) != 0)
377 error (0, 0, "%s: DWARF abbreviation does not end with 2 zeros",
388 #define IS_DIR_SEPARATOR(c) ((c)=='/')
391 canonicalize_path (const char *s, char *d)
396 if (IS_DIR_SEPARATOR (*s))
399 if (IS_DIR_SEPARATOR (*s) && !IS_DIR_SEPARATOR (s[1]))
401 /* Special case for "//foo" meaning a Posix namespace
405 while (IS_DIR_SEPARATOR (*s))
412 /* At this point, we're always at the beginning of a path
415 if (s[0] == '.' && (s[1] == 0 || IS_DIR_SEPARATOR (s[1])))
419 while (IS_DIR_SEPARATOR (*s))
423 else if (s[0] == '.' && s[1] == '.'
424 && (s[2] == 0 || IS_DIR_SEPARATOR (s[2])))
426 char *pre = d - 1; /* includes slash */
427 while (droot < pre && IS_DIR_SEPARATOR (*pre))
429 if (droot <= pre && ! IS_DIR_SEPARATOR (*pre))
431 while (droot < pre && ! IS_DIR_SEPARATOR (*pre))
433 /* pre now points to the slash */
436 if (pre + 3 == d && pre[0] == '.' && pre[1] == '.')
446 while (IS_DIR_SEPARATOR (*s))
458 while (*s && ! IS_DIR_SEPARATOR (*s))
462 if (IS_DIR_SEPARATOR (*s))
465 while (IS_DIR_SEPARATOR (*s))
469 while (droot < d && IS_DIR_SEPARATOR (d[-1]))
479 has_prefix (const char *str,
485 str_len = strlen (str);
486 prefix_len = strlen (prefix);
488 if (str_len < prefix_len)
491 return strncmp (str, prefix, prefix_len) == 0;
494 static int dirty_elf;
496 dirty_section (unsigned int sec)
498 elf_flagdata (debug_sections[sec].elf_data, ELF_C_SET, ELF_F_DIRTY);
503 edit_dwarf2_line (DSO *dso, uint32_t off, char *comp_dir, int phase)
505 unsigned char *ptr = debug_sections[DEBUG_LINE].data, *dir;
507 unsigned char *endsec = ptr + debug_sections[DEBUG_LINE].size;
508 unsigned char *endcu, *endprol;
510 unsigned char opcode_base;
511 uint32_t value, dirt_cnt;
512 size_t comp_dir_len = strlen (comp_dir);
513 size_t abs_file_cnt = 0, abs_dir_cnt = 0;
521 endcu += read_32 (ptr);
522 if (endcu == ptr + 0xffffffff)
524 error (0, 0, "%s: 64-bit DWARF not supported", dso->filename);
530 error (0, 0, "%s: .debug_line CU does not fit into section",
535 value = read_16 (ptr);
536 if (value != 2 && value != 3 && value != 4)
538 error (0, 0, "%s: DWARF version %d unhandled", dso->filename,
544 endprol += read_32 (ptr);
547 error (0, 0, "%s: .debug_line CU prologue does not fit into CU",
552 line_base = (char) (ptr[2 + (value >= 4)] & 0xff);
553 opcode_base = ptr[4 + (value >= 4)];
554 ptr = dir = ptr + 4 + (value >= 4) + opcode_base;
560 ptr = (unsigned char *) strchr ((char *)ptr, 0) + 1;
564 dirt = (char **) alloca (value * sizeof (unsigned char *));
565 dirt[0] = (unsigned char *) ".";
570 dirt[dirt_cnt++] = (char *)ptr;
571 ptr = (unsigned char *) strchr ((char *)ptr, 0) + 1;
579 size_t file_len, dir_len;
582 ptr = (unsigned char *) strchr ((char *)ptr, 0) + 1;
583 value = read_uleb128 (ptr);
585 if (value >= dirt_cnt)
587 error (0, 0, "%s: Wrong directory table index %u",
588 dso->filename, value);
591 file_len = strlen (file);
592 dir_len = strlen ((char *)dirt[value]);
593 s = malloc (comp_dir_len + 1 + file_len + 1 + dir_len + 1);
596 error (0, ENOMEM, "%s: Reading file table", dso->filename);
601 memcpy (s, file, file_len + 1);
602 if (dest_dir && has_prefix (file, base_dir))
605 else if (*dirt[value] == '/')
607 memcpy (s, dirt[value], dir_len);
609 memcpy (s + dir_len + 1, file, file_len + 1);
614 if (comp_dir_len != 0)
616 memcpy (s, comp_dir, comp_dir_len);
617 s[comp_dir_len] = '/';
618 p += comp_dir_len + 1;
620 memcpy (p, dirt[value], dir_len);
622 memcpy (p + dir_len + 1, file, file_len + 1);
624 canonicalize_path (s, s);
625 if (list_file_fd != -1)
628 if (base_dir == NULL)
630 else if (has_prefix (s, base_dir))
631 p = s + strlen (base_dir);
632 else if (has_prefix (s, dest_dir))
633 p = s + strlen (dest_dir);
637 size_t size = strlen (p) + 1;
640 ssize_t ret = write (list_file_fd, p, size);
658 char *srcptr, *buf = NULL;
659 size_t base_len = strlen (base_dir);
660 size_t dest_len = strlen (dest_dir);
663 if (dest_len == base_len)
667 srcptr = buf = malloc (ptr - dir);
668 memcpy (srcptr, dir, ptr - dir);
674 srcptr = (char *)dir;
678 size_t len = strlen ((char *)srcptr) + 1;
679 const char *readptr = srcptr;
681 char *orig = strdup ((const char *) srcptr);
683 if (*srcptr == '/' && has_prefix ((char *)srcptr, base_dir))
685 if (dest_len < base_len)
687 memcpy (ptr, dest_dir, dest_len);
693 shrank += srcptr - readptr;
694 canonicalize_path ((char *)readptr, (char *)ptr);
695 len = strlen ((char *)ptr) + 1;
699 if (memcmp (orig, ptr - len, len))
700 dirty_section (DEBUG_STR);
709 error (EXIT_FAILURE, 0,
710 "canonicalization unexpectedly shrank by one character");
714 memset (ptr, 'X', shrank);
720 if (abs_dir_cnt + abs_file_cnt != 0)
722 size_t len = (abs_dir_cnt + abs_file_cnt) * (base_len - dest_len);
725 error (EXIT_FAILURE, 0, "-b arg has to be either the same length as -d arg, or more than 1 char longer");
726 memset (ptr, 'X', len - 1);
735 size_t len = strlen ((char *)srcptr) + 1;
737 if (*srcptr == '/' && has_prefix ((char *)srcptr, base_dir))
739 memcpy (ptr, dest_dir, dest_len);
740 if (dest_len < base_len)
742 memmove (ptr + dest_len, srcptr + base_len,
744 ptr += dest_len - base_len;
746 dirty_section (DEBUG_STR);
748 else if ((char *)ptr != srcptr)
749 memmove (ptr, srcptr, len);
752 dir = (unsigned char *)srcptr;
753 read_uleb128 (srcptr);
754 read_uleb128 (srcptr);
755 read_uleb128 (srcptr);
757 memmove (ptr, dir, (unsigned char *)srcptr - dir);
758 ptr += (unsigned char *)srcptr - dir;
765 /* fill the rest until the line number program starts with NOP opcode */
766 memset(ptr, opcode_base - line_base, endprol - ptr);
767 /* don't touch the line number program */
771 static unsigned char *
772 edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase)
782 for (i = 0; i < t->nattr; ++i)
784 uint32_t form = t->attr[i].form;
786 size_t base_len, dest_len;
790 if (t->attr[i].attr == DW_AT_stmt_list)
792 if (form == DW_FORM_data4
793 || form == DW_FORM_sec_offset)
795 list_offs = do_read_32_relocated (ptr);
800 if (t->attr[i].attr == DW_AT_comp_dir)
802 if (form == DW_FORM_string)
805 comp_dir = strdup ((char *)ptr);
807 if (phase == 1 && dest_dir && has_prefix ((char *)ptr, base_dir))
809 base_len = strlen (base_dir);
810 dest_len = strlen (dest_dir);
812 memcpy (ptr, dest_dir, dest_len);
813 if (dest_len < base_len)
815 memset(ptr + dest_len, '/',
816 base_len - dest_len);
819 dirty_section (DEBUG_INFO);
822 else if (form == DW_FORM_strp &&
823 debug_sections[DEBUG_STR].data)
827 dir = (char *) debug_sections[DEBUG_STR].data
828 + do_read_32_relocated (ptr);
831 comp_dir = strdup (dir);
833 if (phase == 1 && dest_dir && has_prefix (dir, base_dir))
835 base_len = strlen (base_dir);
836 dest_len = strlen (dest_dir);
838 memcpy (dir, dest_dir, dest_len);
839 if (dest_len < base_len)
841 memmove (dir + dest_len, dir + base_len,
842 strlen (dir + base_len) + 1);
844 dirty_section (DEBUG_STR);
848 else if ((t->tag == DW_TAG_compile_unit
849 || t->tag == DW_TAG_partial_unit)
850 && t->attr[i].attr == DW_AT_name
851 && form == DW_FORM_strp
852 && debug_sections[DEBUG_STR].data)
856 name = (char *) debug_sections[DEBUG_STR].data
857 + do_read_32_relocated (ptr);
858 if (*name == '/' && comp_dir == NULL)
860 char *enddir = strrchr (name, '/');
864 comp_dir = malloc (enddir - name + 1);
865 memcpy (comp_dir, name, enddir - name);
866 comp_dir [enddir - name] = '\0';
869 comp_dir = strdup ("/");
872 if (phase == 1 && dest_dir && has_prefix (name, base_dir))
874 base_len = strlen (base_dir);
875 dest_len = strlen (dest_dir);
877 memcpy (name, dest_dir, dest_len);
878 if (dest_len < base_len)
880 memmove (name + dest_len, name + base_len,
881 strlen (name + base_len) + 1);
883 dirty_section (DEBUG_STR);
889 case DW_FORM_ref_addr:
895 case DW_FORM_flag_present:
911 case DW_FORM_sec_offset:
916 case DW_FORM_ref_sig8:
920 case DW_FORM_ref_udata:
928 ptr = (unsigned char *) strchr ((char *)ptr, '\0') + 1;
930 case DW_FORM_indirect:
931 form = read_uleb128 (ptr);
938 form = DW_FORM_block1;
942 form = DW_FORM_block1;
945 case DW_FORM_exprloc:
946 len = read_uleb128 (ptr);
947 form = DW_FORM_block1;
948 assert (len < UINT_MAX);
951 error (0, 0, "%s: Unknown DWARF DW_FORM_%d", dso->filename,
956 if (form == DW_FORM_block1)
963 /* Ensure the CU current directory will exist even if only empty. Source
964 filenames possibly located in its parent directories refer relatively to
965 it and the debugger (GDB) cannot safely optimize out the missing
966 CU current dir subdirectories. */
967 if (comp_dir && list_file_fd != -1)
972 if (base_dir && has_prefix (comp_dir, base_dir))
973 p = comp_dir + strlen (base_dir);
974 else if (dest_dir && has_prefix (comp_dir, dest_dir))
975 p = comp_dir + strlen (dest_dir);
979 size = strlen (p) + 1;
982 ssize_t ret = write (list_file_fd, p, size);
990 if (found_list_offs && comp_dir)
991 edit_dwarf2_line (dso, list_offs, comp_dir, phase);
999 rel_cmp (const void *a, const void *b)
1001 REL *rela = (REL *) a, *relb = (REL *) b;
1003 if (rela->ptr < relb->ptr)
1006 if (rela->ptr > relb->ptr)
1013 edit_dwarf2 (DSO *dso)
1019 for (i = 0; debug_sections[i].name; ++i)
1021 debug_sections[i].data = NULL;
1022 debug_sections[i].size = 0;
1023 debug_sections[i].sec = 0;
1024 debug_sections[i].relsec = 0;
1028 for (i = 1; i < dso->ehdr.e_shnum; ++i)
1029 if (! (dso->shdr[i].sh_flags & (SHF_ALLOC | SHF_WRITE | SHF_EXECINSTR))
1030 && dso->shdr[i].sh_size)
1032 const char *name = strptr (dso, dso->ehdr.e_shstrndx,
1033 dso->shdr[i].sh_name);
1035 if (strncmp (name, ".debug_", sizeof (".debug_") - 1) == 0)
1037 for (j = 0; debug_sections[j].name; ++j)
1038 if (strcmp (name, debug_sections[j].name) == 0)
1040 if (debug_sections[j].data)
1042 error (0, 0, "%s: Found two copies of %s section",
1043 dso->filename, name);
1048 data = elf_rawdata (scn, NULL);
1049 assert (data != NULL && data->d_buf != NULL);
1050 assert (elf_rawdata (scn, data) == NULL);
1051 assert (data->d_off == 0);
1052 assert (data->d_size == dso->shdr[i].sh_size);
1053 debug_sections[j].data = data->d_buf;
1054 debug_sections[j].elf_data = data;
1055 debug_sections[j].size = data->d_size;
1056 debug_sections[j].sec = i;
1060 if (debug_sections[j].name == NULL)
1062 error (0, 0, "%s: Unknown debugging section %s",
1063 dso->filename, name);
1066 else if (dso->ehdr.e_type == ET_REL
1067 && ((dso->shdr[i].sh_type == SHT_REL
1068 && strncmp (name, ".rel.debug_",
1069 sizeof (".rel.debug_") - 1) == 0)
1070 || (dso->shdr[i].sh_type == SHT_RELA
1071 && strncmp (name, ".rela.debug_",
1072 sizeof (".rela.debug_") - 1) == 0)))
1074 for (j = 0; debug_sections[j].name; ++j)
1075 if (strcmp (name + sizeof (".rel") - 1
1076 + (dso->shdr[i].sh_type == SHT_RELA),
1077 debug_sections[j].name) == 0)
1079 debug_sections[j].relsec = i;
1085 if (dso->ehdr.e_ident[EI_DATA] == ELFDATA2LSB)
1087 do_read_16 = buf_read_ule16;
1088 do_read_32 = buf_read_ule32;
1089 write_32 = dwarf2_write_le32;
1091 else if (dso->ehdr.e_ident[EI_DATA] == ELFDATA2MSB)
1093 do_read_16 = buf_read_ube16;
1094 do_read_32 = buf_read_ube32;
1095 write_32 = dwarf2_write_be32;
1099 error (0, 0, "%s: Wrong ELF data enconding", dso->filename);
1103 if (debug_sections[DEBUG_INFO].data != NULL)
1105 unsigned char *ptr, *endcu, *endsec;
1108 struct abbrev_tag tag, *t;
1112 if (debug_sections[DEBUG_INFO].relsec)
1118 GElf_Addr base = dso->shdr[debug_sections[DEBUG_INFO].sec].sh_addr;
1119 Elf_Data *symdata = NULL;
1122 i = debug_sections[DEBUG_INFO].relsec;
1124 data = elf_getdata (scn, NULL);
1125 assert (data != NULL && data->d_buf != NULL);
1126 assert (elf_getdata (scn, data) == NULL);
1127 assert (data->d_off == 0);
1128 assert (data->d_size == dso->shdr[i].sh_size);
1129 maxndx = dso->shdr[i].sh_size / dso->shdr[i].sh_entsize;
1130 relbuf = malloc (maxndx * sizeof (REL));
1131 reltype = dso->shdr[i].sh_type;
1133 error (1, errno, "%s: Could not allocate memory", dso->filename);
1135 symdata = elf_getdata (dso->scn[dso->shdr[i].sh_link], NULL);
1136 assert (symdata != NULL && symdata->d_buf != NULL);
1137 assert (elf_getdata (dso->scn[dso->shdr[i].sh_link], symdata)
1139 assert (symdata->d_off == 0);
1140 assert (symdata->d_size
1141 == dso->shdr[dso->shdr[i].sh_link].sh_size);
1143 for (ndx = 0, relend = relbuf; ndx < maxndx; ++ndx)
1145 if (dso->shdr[i].sh_type == SHT_REL)
1147 gelf_getrel (data, ndx, &rel);
1148 rela.r_offset = rel.r_offset;
1149 rela.r_info = rel.r_info;
1153 gelf_getrela (data, ndx, &rela);
1154 gelf_getsym (symdata, ELF64_R_SYM (rela.r_info), &sym);
1155 /* Relocations against section symbols are uninteresting
1157 if (dso->shdr[i].sh_type == SHT_REL && sym.st_value == 0)
1159 /* Only consider relocations against .debug_str, .debug_line
1160 and .debug_abbrev. */
1161 if (sym.st_shndx != debug_sections[DEBUG_STR].sec
1162 && sym.st_shndx != debug_sections[DEBUG_LINE].sec
1163 && sym.st_shndx != debug_sections[DEBUG_ABBREV].sec)
1165 rela.r_addend += sym.st_value;
1166 rtype = ELF64_R_TYPE (rela.r_info);
1167 switch (dso->ehdr.e_machine)
1170 case EM_SPARC32PLUS:
1172 if (rtype != R_SPARC_32 && rtype != R_SPARC_UA32)
1176 if (rtype != R_386_32)
1181 if (rtype != R_PPC_ADDR32 && rtype != R_PPC_UADDR32)
1185 if (rtype != R_390_32)
1189 if (rtype != R_IA64_SECREL32LSB)
1193 if (rtype != R_X86_64_32)
1197 if (rtype != R_ALPHA_REFLONG)
1202 error (1, 0, "%s: Unhandled relocation %d in .debug_info section",
1203 dso->filename, rtype);
1205 relend->ptr = debug_sections[DEBUG_INFO].data
1206 + (rela.r_offset - base);
1207 relend->addend = rela.r_addend;
1210 if (relbuf == relend)
1217 qsort (relbuf, relend - relbuf, sizeof (REL), rel_cmp);
1220 for (phase = 0; phase < 2; phase++)
1222 ptr = debug_sections[DEBUG_INFO].data;
1224 endsec = ptr + debug_sections[DEBUG_INFO].size;
1225 while (ptr < endsec)
1227 if (ptr + 11 > endsec)
1229 error (0, 0, "%s: .debug_info CU header too small",
1235 endcu += read_32 (ptr);
1236 if (endcu == ptr + 0xffffffff)
1238 error (0, 0, "%s: 64-bit DWARF not supported", dso->filename);
1244 error (0, 0, "%s: .debug_info too small", dso->filename);
1248 cu_version = read_16 (ptr);
1249 if (cu_version != 2 && cu_version != 3 && cu_version != 4)
1251 error (0, 0, "%s: DWARF version %d unhandled", dso->filename,
1256 value = read_32_relocated (ptr);
1257 if (value >= debug_sections[DEBUG_ABBREV].size)
1259 if (debug_sections[DEBUG_ABBREV].data == NULL)
1260 error (0, 0, "%s: .debug_abbrev not present", dso->filename);
1262 error (0, 0, "%s: DWARF CU abbrev offset too large",
1269 ptr_size = read_1 (ptr);
1270 if (ptr_size != 4 && ptr_size != 8)
1272 error (0, 0, "%s: Invalid DWARF pointer size %d",
1273 dso->filename, ptr_size);
1277 else if (read_1 (ptr) != ptr_size)
1279 error (0, 0, "%s: DWARF pointer size differs between CUs",
1284 abbrev = read_abbrev (dso,
1285 debug_sections[DEBUG_ABBREV].data + value);
1291 tag.entry = read_uleb128 (ptr);
1294 t = htab_find_with_hash (abbrev, &tag, tag.entry);
1297 error (0, 0, "%s: Could not find DWARF abbreviation %d",
1298 dso->filename, tag.entry);
1299 htab_delete (abbrev);
1303 ptr = edit_attributes (dso, ptr, t, phase);
1308 htab_delete (abbrev);
1317 static struct poptOption optionsTable[] = {
1318 { "base-dir", 'b', POPT_ARG_STRING, &base_dir, 0,
1319 "base build directory of objects", NULL },
1320 { "dest-dir", 'd', POPT_ARG_STRING, &dest_dir, 0,
1321 "directory to rewrite base-dir into", NULL },
1322 { "list-file", 'l', POPT_ARG_STRING, &list_file, 0,
1323 "file where to put list of source and header file names", NULL },
1324 { "build-id", 'i', POPT_ARG_NONE, &do_build_id, 0,
1325 "recompute build ID note and print ID on stdout", NULL },
1327 { NULL, 0, 0, NULL, 0, NULL, NULL }
1331 fdopen_dso (int fd, const char *name)
1338 elf = elf_begin (fd, ELF_C_RDWR_MMAP, NULL);
1341 error (0, 0, "cannot open ELF file: %s", elf_errmsg (-1));
1345 if (elf_kind (elf) != ELF_K_ELF)
1347 error (0, 0, "\"%s\" is not an ELF file", name);
1351 if (gelf_getehdr (elf, &ehdr) == NULL)
1353 error (0, 0, "cannot get the ELF header: %s",
1358 if (ehdr.e_type != ET_DYN && ehdr.e_type != ET_EXEC && ehdr.e_type != ET_REL)
1360 error (0, 0, "\"%s\" is not a shared library", name);
1364 /* Allocate DSO structure. Leave place for additional 20 new section
1367 malloc (sizeof(DSO) + (ehdr.e_shnum + 20) * sizeof(GElf_Shdr)
1368 + (ehdr.e_shnum + 20) * sizeof(Elf_Scn *));
1371 error (0, ENOMEM, "Could not open DSO");
1375 elf_flagelf (elf, ELF_C_SET, ELF_F_LAYOUT);
1377 memset (dso, 0, sizeof(DSO));
1380 dso->scn = (Elf_Scn **) &dso->shdr[ehdr.e_shnum + 20];
1382 for (i = 0; i < ehdr.e_shnum; ++i)
1384 dso->scn[i] = elf_getscn (elf, i);
1385 gelf_getshdr (dso->scn[i], dso->shdr + i);
1388 dso->filename = (const char *) strdup (name);
1394 free ((char *) dso->filename);
1404 static const pgpHashAlgo algorithms[] = { PGPHASHALGO_MD5,
1405 PGPHASHALGO_SHA1, PGPHASHALGO_SHA256, PGPHASHALGO_SHA384, PGPHASHALGO_SHA512 };
1407 /* Compute a fresh build ID bit-string from the editted file contents. */
1409 handle_build_id (DSO *dso, Elf_Data *build_id,
1410 size_t build_id_offset, size_t build_id_size)
1413 pgpHashAlgo algorithm;
1414 int i = sizeof(algorithms)/sizeof(algorithms[0]);
1415 void *digest = NULL;
1420 algorithm = algorithms[i];
1421 if (rpmDigestLength(algorithm) == build_id_size)
1426 fprintf (stderr, "Cannot handle %Zu-byte build ID\n", build_id_size);
1433 if (elf_update (dso->elf, ELF_C_NULL) < 0)
1435 fprintf (stderr, "Failed to update file: %s\n",
1436 elf_errmsg (elf_errno ()));
1440 /* Clear the old bits so they do not affect the new hash. */
1441 memset ((char *) build_id->d_buf + build_id_offset, 0, build_id_size);
1443 ctx = rpmDigestInit(algorithm, 0);
1445 /* Slurp the relevant header bits and section contents and feed them
1446 into the hash function. The only bits we ignore are the offset
1447 fields in ehdr and shdrs, since the semantically identical ELF file
1448 could be written differently if it doesn't change the phdr layout.
1449 We always use the GElf (i.e. Elf64) formats for the bits to hash
1450 since it is convenient. It doesn't matter whether this is an Elf32
1451 or Elf64 object, only that we are consistent in what bits feed the
1452 hash so it comes out the same for the same file contents. */
1460 Elf_Data x = { .d_version = EV_CURRENT, .d_buf = &u };
1462 x.d_type = ELF_T_EHDR;
1463 x.d_size = sizeof u.ehdr;
1465 u.ehdr.e_phoff = u.ehdr.e_shoff = 0;
1466 if (elf64_xlatetom (&x, &x, dso->ehdr.e_ident[EI_DATA]) == NULL)
1469 fprintf (stderr, "Failed to compute header checksum: %s\n",
1470 elf_errmsg (elf_errno ()));
1474 x.d_type = ELF_T_PHDR;
1475 x.d_size = sizeof u.phdr;
1476 for (i = 0; i < dso->ehdr.e_phnum; ++i)
1478 if (gelf_getphdr (dso->elf, i, &u.phdr) == NULL)
1480 if (elf64_xlatetom (&x, &x, dso->ehdr.e_ident[EI_DATA]) == NULL)
1482 rpmDigestUpdate(ctx, x.d_buf, x.d_size);
1485 x.d_type = ELF_T_SHDR;
1486 x.d_size = sizeof u.shdr;
1487 for (i = 0; i < dso->ehdr.e_shnum; ++i)
1488 if (dso->scn[i] != NULL)
1490 u.shdr = dso->shdr[i];
1491 u.shdr.sh_offset = 0;
1492 if (elf64_xlatetom (&x, &x, dso->ehdr.e_ident[EI_DATA]) == NULL)
1494 rpmDigestUpdate(ctx, x.d_buf, x.d_size);
1496 if (u.shdr.sh_type != SHT_NOBITS)
1498 Elf_Data *d = elf_rawdata (dso->scn[i], NULL);
1501 rpmDigestUpdate(ctx, d->d_buf, d->d_size);
1506 rpmDigestFinal(ctx, &digest, &len, 0);
1507 memcpy((unsigned char *)build_id->d_buf + build_id_offset, digest, build_id_size);
1510 elf_flagdata (build_id, ELF_C_SET, ELF_F_DIRTY);
1513 /* Now format the build ID bits in hex to print out. */
1515 const uint8_t * id = (uint8_t *)build_id->d_buf + build_id_offset;
1516 char *hex = pgpHexStr(id, build_id_size);
1523 main (int argc, char *argv[])
1528 poptContext optCon; /* context for parsing command-line options */
1531 struct stat stat_buf;
1533 Elf_Data *build_id = NULL;
1534 size_t build_id_offset = 0, build_id_size = 0;
1536 optCon = poptGetContext("debugedit", argc, (const char **)argv, optionsTable, 0);
1538 while ((nextopt = poptGetNextOpt (optCon)) > 0 || nextopt == POPT_ERROR_BADOPT)
1543 fprintf (stderr, "Error on option %s: %s.\nRun '%s --help' to see a full list of available command line options.\n",
1544 poptBadOption (optCon, 0),
1545 poptStrerror (nextopt),
1550 args = poptGetArgs (optCon);
1551 if (args == NULL || args[0] == NULL || args[1] != NULL)
1553 poptPrintHelp(optCon, stdout, 0);
1557 if (dest_dir != NULL)
1559 if (base_dir == NULL)
1561 fprintf (stderr, "You must specify a base dir if you specify a dest dir\n");
1564 if (strlen (dest_dir) > strlen (base_dir))
1566 fprintf (stderr, "Dest dir longer than base dir is not supported\n");
1571 /* Make sure there are trailing slashes in dirs */
1572 if (base_dir != NULL && base_dir[strlen (base_dir)-1] != '/')
1574 p = malloc (strlen (base_dir) + 2);
1575 strcpy (p, base_dir);
1580 if (dest_dir != NULL && dest_dir[strlen (dest_dir)-1] != '/')
1582 p = malloc (strlen (dest_dir) + 2);
1583 strcpy (p, dest_dir);
1589 if (list_file != NULL)
1591 list_file_fd = open (list_file, O_WRONLY|O_CREAT|O_APPEND, 0644);
1596 if (elf_version(EV_CURRENT) == EV_NONE)
1598 fprintf (stderr, "library out of date\n");
1602 if (stat(file, &stat_buf) < 0)
1604 fprintf (stderr, "Failed to open input file '%s': %s\n", file, strerror(errno));
1608 /* Make sure we can read and write */
1609 chmod (file, stat_buf.st_mode | S_IRUSR | S_IWUSR);
1611 fd = open (file, O_RDWR);
1614 fprintf (stderr, "Failed to open input file '%s': %s\n", file, strerror(errno));
1618 dso = fdopen_dso (fd, file);
1622 for (i = 1; i < dso->ehdr.e_shnum; i++)
1626 switch (dso->shdr[i].sh_type)
1629 name = strptr (dso, dso->ehdr.e_shstrndx, dso->shdr[i].sh_name);
1630 /* TODO: Handle stabs */
1631 if (strcmp (name, ".stab") == 0)
1633 fprintf (stderr, "Stabs debuginfo not supported: %s\n", file);
1636 if (strcmp (name, ".debug_info") == 0)
1642 && build_id == NULL && (dso->shdr[i].sh_flags & SHF_ALLOC))
1644 /* Look for a build-ID note here. */
1645 Elf_Data *data = elf_rawdata (elf_getscn (dso->elf, i), NULL);
1649 .d_version = EV_CURRENT, .d_type = ELF_T_NHDR,
1650 .d_buf = &nh, .d_size = sizeof nh
1653 src.d_buf = data->d_buf;
1654 assert (sizeof (Elf32_Nhdr) == sizeof (Elf64_Nhdr));
1655 while ((char *) data->d_buf + data->d_size -
1656 (char *) src.d_buf > (int) sizeof nh
1657 && elf32_xlatetom (&dst, &src, dso->ehdr.e_ident[EI_DATA]))
1659 Elf32_Word len = sizeof nh + nh.n_namesz;
1660 len = (len + 3) & ~3;
1662 if (nh.n_namesz == sizeof "GNU" && nh.n_type == 3
1663 && !memcmp ((char *) src.d_buf + sizeof nh, "GNU", sizeof "GNU"))
1666 build_id_offset = (char *) src.d_buf + len -
1667 (char *) data->d_buf;
1668 build_id_size = nh.n_descsz;
1673 len = (len + 3) & ~3;
1674 src.d_buf = (char *) src.d_buf + len;
1683 if (do_build_id && build_id != NULL)
1684 handle_build_id (dso, build_id, build_id_offset, build_id_size);
1686 if (elf_update (dso->elf, ELF_C_WRITE) < 0)
1688 fprintf (stderr, "Failed to write file: %s\n", elf_errmsg (elf_errno()));
1691 if (elf_end (dso->elf) < 0)
1693 fprintf (stderr, "elf_end failed: %s\n", elf_errmsg (elf_errno()));
1698 /* Restore old access rights */
1699 chmod (file, stat_buf.st_mode);
1701 poptFreeContext (optCon);