1 /* Copyright (C) 2001, 2002, 2003, 2005, 2007, 2009, 2010 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 #include <rpm/rpmio.h>
43 #include <rpm/rpmpgp.h>
44 #include "tools/hashtab.h"
46 #define DW_TAG_partial_unit 0x3c
48 char *base_dir = NULL;
49 char *dest_dir = NULL;
50 char *list_file = NULL;
51 int list_file_fd = -1;
70 #define read_uleb128(ptr) ({ \
71 unsigned int ret = 0; \
77 ret |= (c & 0x7f) << shift; \
86 static uint16_t (*do_read_16) (unsigned char *ptr);
87 static uint32_t (*do_read_32) (unsigned char *ptr);
88 static void (*write_32) (unsigned char *ptr, GElf_Addr val);
91 static int cu_version;
93 static inline uint16_t
94 buf_read_ule16 (unsigned char *data)
96 return data[0] | (data[1] << 8);
99 static inline uint16_t
100 buf_read_ube16 (unsigned char *data)
102 return data[1] | (data[0] << 8);
105 static inline uint32_t
106 buf_read_ule32 (unsigned char *data)
108 return data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
111 static inline uint32_t
112 buf_read_ube32 (unsigned char *data)
114 return data[3] | (data[2] << 8) | (data[1] << 16) | (data[0] << 24);
118 strptr (DSO *dso, int sec, off_t offset)
124 if (offset >= 0 && (GElf_Addr) offset < dso->shdr[sec].sh_size)
127 while ((data = elf_rawdata (scn, data)) != NULL)
130 && offset >= data->d_off
131 && offset < data->d_off + data->d_size)
132 return (const char *) data->d_buf + (offset - data->d_off);
140 #define read_1(ptr) *ptr++
142 #define read_16(ptr) ({ \
143 uint16_t ret = do_read_16 (ptr); \
148 #define read_32(ptr) ({ \
149 uint32_t ret = do_read_32 (ptr); \
154 REL *relptr, *relend;
157 #define do_read_32_relocated(ptr) ({ \
158 uint32_t dret = do_read_32 (ptr); \
161 while (relptr < relend && relptr->ptr < ptr) \
163 if (relptr < relend && relptr->ptr == ptr) \
165 if (reltype == SHT_REL) \
166 dret += relptr->addend; \
168 dret = relptr->addend; \
174 #define read_32_relocated(ptr) ({ \
175 uint32_t ret = do_read_32_relocated (ptr); \
181 dwarf2_write_le32 (unsigned char *p, GElf_Addr val)
183 uint32_t v = (uint32_t) val;
193 dwarf2_write_be32 (unsigned char *p, GElf_Addr val)
195 uint32_t v = (uint32_t) val;
213 #define DEBUG_ABBREV 1
215 #define DEBUG_ARANGES 3
216 #define DEBUG_PUBNAMES 4
217 #define DEBUG_PUBTYPES 5
218 #define DEBUG_MACINFO 6
221 #define DEBUG_FRAME 9
222 #define DEBUG_RANGES 10
223 { ".debug_info", NULL, NULL, 0, 0, 0 },
224 { ".debug_abbrev", NULL, NULL, 0, 0, 0 },
225 { ".debug_line", NULL, NULL, 0, 0, 0 },
226 { ".debug_aranges", NULL, NULL, 0, 0, 0 },
227 { ".debug_pubnames", NULL, NULL, 0, 0, 0 },
228 { ".debug_pubtypes", NULL, NULL, 0, 0, 0 },
229 { ".debug_macinfo", NULL, NULL, 0, 0, 0 },
230 { ".debug_loc", NULL, NULL, 0, 0, 0 },
231 { ".debug_str", NULL, NULL, 0, 0, 0 },
232 { ".debug_frame", NULL, NULL, 0, 0, 0 },
233 { ".debug_ranges", NULL, NULL, 0, 0, 0 },
234 { NULL, NULL, NULL, 0, 0, 0 }
248 struct abbrev_attr attr[0];
252 abbrev_hash (const void *p)
254 struct abbrev_tag *t = (struct abbrev_tag *)p;
260 abbrev_eq (const void *p, const void *q)
262 struct abbrev_tag *t1 = (struct abbrev_tag *)p;
263 struct abbrev_tag *t2 = (struct abbrev_tag *)q;
265 return t1->entry == t2->entry;
275 read_abbrev (DSO *dso, unsigned char *ptr)
277 htab_t h = htab_try_create (50, abbrev_hash, abbrev_eq, abbrev_del);
278 unsigned int attr, form;
279 struct abbrev_tag *t;
286 error (0, ENOMEM, "%s: Could not read .debug_abbrev", dso->filename);
292 while ((attr = read_uleb128 (ptr)) != 0)
295 t = malloc (sizeof (*t) + size * sizeof (struct abbrev_attr));
300 slot = htab_find_slot (h, t, INSERT);
308 error (0, 0, "%s: Duplicate DWARF abbreviation %d", dso->filename,
314 t->tag = read_uleb128 (ptr);
315 ++ptr; /* skip children flag. */
316 while ((attr = read_uleb128 (ptr)) != 0)
318 if (t->nattr == size)
321 t = realloc (t, sizeof (*t) + size * sizeof (struct abbrev_attr));
325 form = read_uleb128 (ptr);
326 if (form == 2 || form > DW_FORM_indirect)
328 error (0, 0, "%s: Unknown DWARF DW_FORM_%d", dso->filename, form);
333 t->attr[t->nattr].attr = attr;
334 t->attr[t->nattr++].form = form;
336 if (read_uleb128 (ptr) != 0)
338 error (0, 0, "%s: DWARF abbreviation does not end with 2 zeros",
349 #define IS_DIR_SEPARATOR(c) ((c)=='/')
352 canonicalize_path (const char *s, char *d)
357 if (IS_DIR_SEPARATOR (*s))
360 if (IS_DIR_SEPARATOR (*s) && !IS_DIR_SEPARATOR (s[1]))
362 /* Special case for "//foo" meaning a Posix namespace
366 while (IS_DIR_SEPARATOR (*s))
373 /* At this point, we're always at the beginning of a path
376 if (s[0] == '.' && (s[1] == 0 || IS_DIR_SEPARATOR (s[1])))
380 while (IS_DIR_SEPARATOR (*s))
384 else if (s[0] == '.' && s[1] == '.'
385 && (s[2] == 0 || IS_DIR_SEPARATOR (s[2])))
387 char *pre = d - 1; /* includes slash */
388 while (droot < pre && IS_DIR_SEPARATOR (*pre))
390 if (droot <= pre && ! IS_DIR_SEPARATOR (*pre))
392 while (droot < pre && ! IS_DIR_SEPARATOR (*pre))
394 /* pre now points to the slash */
397 if (pre + 3 == d && pre[0] == '.' && pre[1] == '.')
407 while (IS_DIR_SEPARATOR (*s))
419 while (*s && ! IS_DIR_SEPARATOR (*s))
423 if (IS_DIR_SEPARATOR (*s))
426 while (IS_DIR_SEPARATOR (*s))
430 while (droot < d && IS_DIR_SEPARATOR (d[-1]))
440 has_prefix (const char *str,
446 str_len = strlen (str);
447 prefix_len = strlen (prefix);
449 if (str_len < prefix_len)
452 return strncmp (str, prefix, prefix_len) == 0;
455 static int dirty_elf;
457 dirty_section (unsigned int sec)
459 elf_flagdata (debug_sections[sec].elf_data, ELF_C_SET, ELF_F_DIRTY);
464 edit_dwarf2_line (DSO *dso, uint32_t off, char *comp_dir, int phase)
466 unsigned char *ptr = debug_sections[DEBUG_LINE].data, *dir;
467 unsigned char **dirt;
468 unsigned char *endsec = ptr + debug_sections[DEBUG_LINE].size;
469 unsigned char *endcu, *endprol;
470 unsigned char opcode_base;
471 uint32_t value, dirt_cnt;
472 size_t comp_dir_len = strlen (comp_dir);
473 size_t abs_file_cnt = 0, abs_dir_cnt = 0;
481 endcu += read_32 (ptr);
482 if (endcu == ptr + 0xffffffff)
484 error (0, 0, "%s: 64-bit DWARF not supported", dso->filename);
490 error (0, 0, "%s: .debug_line CU does not fit into section",
495 value = read_16 (ptr);
496 if (value != 2 && value != 3)
498 error (0, 0, "%s: DWARF version %d unhandled", dso->filename,
504 endprol += read_32 (ptr);
507 error (0, 0, "%s: .debug_line CU prologue does not fit into CU",
512 opcode_base = ptr[4];
513 ptr = dir = ptr + 4 + opcode_base;
519 ptr = (unsigned char *) strchr ((char *)ptr, 0) + 1;
523 dirt = (unsigned char **) alloca (value * sizeof (unsigned char *));
524 dirt[0] = (unsigned char *) ".";
529 dirt[dirt_cnt++] = ptr;
530 ptr = (unsigned char *) strchr ((char *)ptr, 0) + 1;
538 size_t file_len, dir_len;
541 ptr = (unsigned char *) strchr ((char *)ptr, 0) + 1;
542 value = read_uleb128 (ptr);
544 if (value >= dirt_cnt)
546 error (0, 0, "%s: Wrong directory table index %u",
547 dso->filename, value);
550 file_len = strlen (file);
551 dir_len = strlen ((char *)dirt[value]);
552 s = malloc (comp_dir_len + 1 + file_len + 1 + dir_len + 1);
555 error (0, ENOMEM, "%s: Reading file table", dso->filename);
560 memcpy (s, file, file_len + 1);
561 if (dest_dir && has_prefix (file, base_dir))
564 else if (*dirt[value] == '/')
566 memcpy (s, dirt[value], dir_len);
568 memcpy (s + dir_len + 1, file, file_len + 1);
573 if (comp_dir_len != 0)
575 memcpy (s, comp_dir, comp_dir_len);
576 s[comp_dir_len] = '/';
577 p += comp_dir_len + 1;
579 memcpy (p, dirt[value], dir_len);
581 memcpy (p + dir_len + 1, file, file_len + 1);
583 canonicalize_path (s, s);
584 if (list_file_fd != -1)
587 if (base_dir == NULL)
589 else if (has_prefix (s, base_dir))
590 p = s + strlen (base_dir);
591 else if (has_prefix (s, dest_dir))
592 p = s + strlen (dest_dir);
596 size_t size = strlen (p) + 1;
599 ssize_t ret = write (list_file_fd, p, size);
617 unsigned char *srcptr, *buf = NULL;
618 size_t base_len = strlen (base_dir);
619 size_t dest_len = strlen (dest_dir);
622 if (dest_len == base_len)
626 srcptr = buf = malloc (ptr - dir);
627 memcpy (srcptr, dir, ptr - dir);
634 size_t len = strlen ((char *)srcptr) + 1;
635 const unsigned char *readptr = srcptr;
637 char *orig = strdup ((const char *) srcptr);
639 if (*srcptr == '/' && has_prefix ((char *)srcptr, base_dir))
641 if (dest_len < base_len)
643 memcpy (ptr, dest_dir, dest_len);
649 shrank += srcptr - readptr;
650 canonicalize_path ((char *)readptr, (char *)ptr);
651 len = strlen ((char *)ptr) + 1;
655 if (memcmp (orig, ptr - len, len))
656 dirty_section (DEBUG_STR);
663 error (EXIT_FAILURE, 0,
664 "canonicalization unexpectedly shrank by one character");
667 memset (ptr, 'X', shrank);
673 if (abs_dir_cnt + abs_file_cnt != 0)
675 size_t len = (abs_dir_cnt + abs_file_cnt) * (base_len - dest_len);
678 error (EXIT_FAILURE, 0, "-b arg has to be either the same length as -d arg, or more than 1 char longer");
679 memset (ptr, 'X', len - 1);
688 size_t len = strlen ((char *)srcptr) + 1;
690 if (*srcptr == '/' && has_prefix ((char *)srcptr, base_dir))
692 memcpy (ptr, dest_dir, dest_len);
693 if (dest_len < base_len)
695 memmove (ptr + dest_len, srcptr + base_len,
697 ptr += dest_len - base_len;
699 dirty_section (DEBUG_STR);
701 else if (ptr != srcptr)
702 memmove (ptr, srcptr, len);
706 read_uleb128 (srcptr);
707 read_uleb128 (srcptr);
708 read_uleb128 (srcptr);
710 memmove (ptr, dir, srcptr - dir);
719 static unsigned char *
720 edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase)
730 for (i = 0; i < t->nattr; ++i)
732 uint32_t form = t->attr[i].form;
734 size_t base_len, dest_len;
738 if (t->attr[i].attr == DW_AT_stmt_list)
740 if (form == DW_FORM_data4)
742 list_offs = do_read_32_relocated (ptr);
747 if (t->attr[i].attr == DW_AT_comp_dir)
749 if (form == DW_FORM_string)
752 comp_dir = strdup ((char *)ptr);
754 if (phase == 1 && dest_dir && has_prefix ((char *)ptr, base_dir))
756 base_len = strlen (base_dir);
757 dest_len = strlen (dest_dir);
759 memcpy (ptr, dest_dir, dest_len);
760 if (dest_len < base_len)
762 memset(ptr + dest_len, '/',
763 base_len - dest_len);
766 dirty_section (DEBUG_INFO);
769 else if (form == DW_FORM_strp &&
770 debug_sections[DEBUG_STR].data)
774 dir = (char *) debug_sections[DEBUG_STR].data
775 + do_read_32_relocated (ptr);
778 comp_dir = strdup (dir);
780 if (phase == 1 && dest_dir && has_prefix (dir, base_dir))
782 base_len = strlen (base_dir);
783 dest_len = strlen (dest_dir);
785 memcpy (dir, dest_dir, dest_len);
786 if (dest_len < base_len)
788 memmove (dir + dest_len, dir + base_len,
789 strlen (dir + base_len) + 1);
791 dirty_section (DEBUG_STR);
795 else if ((t->tag == DW_TAG_compile_unit
796 || t->tag == DW_TAG_partial_unit)
797 && t->attr[i].attr == DW_AT_name
798 && form == DW_FORM_strp
799 && debug_sections[DEBUG_STR].data)
803 name = (char *) debug_sections[DEBUG_STR].data
804 + do_read_32_relocated (ptr);
805 if (*name == '/' && comp_dir == NULL)
807 char *enddir = strrchr (name, '/');
811 comp_dir = malloc (enddir - name + 1);
812 memcpy (comp_dir, name, enddir - name);
813 comp_dir [enddir - name] = '\0';
816 comp_dir = strdup ("/");
819 if (phase == 1 && dest_dir && has_prefix (name, base_dir))
821 base_len = strlen (base_dir);
822 dest_len = strlen (dest_dir);
824 memcpy (name, dest_dir, dest_len);
825 if (dest_len < base_len)
827 memmove (name + dest_len, name + base_len,
828 strlen (name + base_len) + 1);
830 dirty_section (DEBUG_STR);
836 case DW_FORM_ref_addr:
863 case DW_FORM_ref_udata:
871 ptr = (unsigned char *) strchr ((char *)ptr, '\0') + 1;
873 case DW_FORM_indirect:
874 form = read_uleb128 (ptr);
881 form = DW_FORM_block1;
885 form = DW_FORM_block1;
888 len = read_uleb128 (ptr);
889 form = DW_FORM_block1;
890 assert (len < UINT_MAX);
893 error (0, 0, "%s: Unknown DWARF DW_FORM_%d", dso->filename,
898 if (form == DW_FORM_block1)
905 /* Ensure the CU current directory will exist even if only empty. Source
906 filenames possibly located in its parent directories refer relatively to
907 it and the debugger (GDB) cannot safely optimize out the missing
908 CU current dir subdirectories. */
909 if (comp_dir && list_file_fd != -1)
914 if (base_dir && has_prefix (comp_dir, base_dir))
915 p = comp_dir + strlen (base_dir);
916 else if (dest_dir && has_prefix (comp_dir, dest_dir))
917 p = comp_dir + strlen (dest_dir);
921 size = strlen (p) + 1;
924 ssize_t ret = write (list_file_fd, p, size);
932 if (found_list_offs && comp_dir)
933 edit_dwarf2_line (dso, list_offs, comp_dir, phase);
941 rel_cmp (const void *a, const void *b)
943 REL *rela = (REL *) a, *relb = (REL *) b;
945 if (rela->ptr < relb->ptr)
948 if (rela->ptr > relb->ptr)
955 edit_dwarf2 (DSO *dso)
961 for (i = 0; debug_sections[i].name; ++i)
963 debug_sections[i].data = NULL;
964 debug_sections[i].size = 0;
965 debug_sections[i].sec = 0;
966 debug_sections[i].relsec = 0;
970 for (i = 1; i < dso->ehdr.e_shnum; ++i)
971 if (! (dso->shdr[i].sh_flags & (SHF_ALLOC | SHF_WRITE | SHF_EXECINSTR))
972 && dso->shdr[i].sh_size)
974 const char *name = strptr (dso, dso->ehdr.e_shstrndx,
975 dso->shdr[i].sh_name);
977 if (strncmp (name, ".debug_", sizeof (".debug_") - 1) == 0)
979 for (j = 0; debug_sections[j].name; ++j)
980 if (strcmp (name, debug_sections[j].name) == 0)
982 if (debug_sections[j].data)
984 error (0, 0, "%s: Found two copies of %s section",
985 dso->filename, name);
990 data = elf_rawdata (scn, NULL);
991 assert (data != NULL && data->d_buf != NULL);
992 assert (elf_rawdata (scn, data) == NULL);
993 assert (data->d_off == 0);
994 assert (data->d_size == dso->shdr[i].sh_size);
995 debug_sections[j].data = data->d_buf;
996 debug_sections[j].elf_data = data;
997 debug_sections[j].size = data->d_size;
998 debug_sections[j].sec = i;
1002 if (debug_sections[j].name == NULL)
1004 error (0, 0, "%s: Unknown debugging section %s",
1005 dso->filename, name);
1008 else if (dso->ehdr.e_type == ET_REL
1009 && ((dso->shdr[i].sh_type == SHT_REL
1010 && strncmp (name, ".rel.debug_",
1011 sizeof (".rel.debug_") - 1) == 0)
1012 || (dso->shdr[i].sh_type == SHT_RELA
1013 && strncmp (name, ".rela.debug_",
1014 sizeof (".rela.debug_") - 1) == 0)))
1016 for (j = 0; debug_sections[j].name; ++j)
1017 if (strcmp (name + sizeof (".rel") - 1
1018 + (dso->shdr[i].sh_type == SHT_RELA),
1019 debug_sections[j].name) == 0)
1021 debug_sections[j].relsec = i;
1027 if (dso->ehdr.e_ident[EI_DATA] == ELFDATA2LSB)
1029 do_read_16 = buf_read_ule16;
1030 do_read_32 = buf_read_ule32;
1031 write_32 = dwarf2_write_le32;
1033 else if (dso->ehdr.e_ident[EI_DATA] == ELFDATA2MSB)
1035 do_read_16 = buf_read_ube16;
1036 do_read_32 = buf_read_ube32;
1037 write_32 = dwarf2_write_be32;
1041 error (0, 0, "%s: Wrong ELF data enconding", dso->filename);
1045 if (debug_sections[DEBUG_INFO].data != NULL)
1047 unsigned char *ptr, *endcu, *endsec;
1050 struct abbrev_tag tag, *t;
1054 if (debug_sections[DEBUG_INFO].relsec)
1060 GElf_Addr base = dso->shdr[debug_sections[DEBUG_INFO].sec].sh_addr;
1061 Elf_Data *symdata = NULL;
1064 i = debug_sections[DEBUG_INFO].relsec;
1066 data = elf_getdata (scn, NULL);
1067 assert (data != NULL && data->d_buf != NULL);
1068 assert (elf_getdata (scn, data) == NULL);
1069 assert (data->d_off == 0);
1070 assert (data->d_size == dso->shdr[i].sh_size);
1071 maxndx = dso->shdr[i].sh_size / dso->shdr[i].sh_entsize;
1072 relbuf = malloc (maxndx * sizeof (REL));
1073 reltype = dso->shdr[i].sh_type;
1075 error (1, errno, "%s: Could not allocate memory", dso->filename);
1077 symdata = elf_getdata (dso->scn[dso->shdr[i].sh_link], NULL);
1078 assert (symdata != NULL && symdata->d_buf != NULL);
1079 assert (elf_getdata (dso->scn[dso->shdr[i].sh_link], symdata)
1081 assert (symdata->d_off == 0);
1082 assert (symdata->d_size
1083 == dso->shdr[dso->shdr[i].sh_link].sh_size);
1085 for (ndx = 0, relend = relbuf; ndx < maxndx; ++ndx)
1087 if (dso->shdr[i].sh_type == SHT_REL)
1089 gelf_getrel (data, ndx, &rel);
1090 rela.r_offset = rel.r_offset;
1091 rela.r_info = rel.r_info;
1095 gelf_getrela (data, ndx, &rela);
1096 gelf_getsym (symdata, ELF64_R_SYM (rela.r_info), &sym);
1097 /* Relocations against section symbols are uninteresting
1099 if (dso->shdr[i].sh_type == SHT_REL && sym.st_value == 0)
1101 /* Only consider relocations against .debug_str, .debug_line
1102 and .debug_abbrev. */
1103 if (sym.st_shndx != debug_sections[DEBUG_STR].sec
1104 && sym.st_shndx != debug_sections[DEBUG_LINE].sec
1105 && sym.st_shndx != debug_sections[DEBUG_ABBREV].sec)
1107 rela.r_addend += sym.st_value;
1108 rtype = ELF64_R_TYPE (rela.r_info);
1109 switch (dso->ehdr.e_machine)
1112 case EM_SPARC32PLUS:
1114 if (rtype != R_SPARC_32 && rtype != R_SPARC_UA32)
1118 if (rtype != R_386_32)
1123 if (rtype != R_PPC_ADDR32 && rtype != R_PPC_UADDR32)
1127 if (rtype != R_390_32)
1131 if (rtype != R_IA64_SECREL32LSB)
1135 if (rtype != R_X86_64_32)
1139 if (rtype != R_ALPHA_REFLONG)
1144 error (1, 0, "%s: Unhandled relocation %d in .debug_info section",
1145 dso->filename, rtype);
1147 relend->ptr = debug_sections[DEBUG_INFO].data
1148 + (rela.r_offset - base);
1149 relend->addend = rela.r_addend;
1152 if (relbuf == relend)
1159 qsort (relbuf, relend - relbuf, sizeof (REL), rel_cmp);
1162 for (phase = 0; phase < 2; phase++)
1164 ptr = debug_sections[DEBUG_INFO].data;
1166 endsec = ptr + debug_sections[DEBUG_INFO].size;
1167 while (ptr < endsec)
1169 if (ptr + 11 > endsec)
1171 error (0, 0, "%s: .debug_info CU header too small",
1177 endcu += read_32 (ptr);
1178 if (endcu == ptr + 0xffffffff)
1180 error (0, 0, "%s: 64-bit DWARF not supported", dso->filename);
1186 error (0, 0, "%s: .debug_info too small", dso->filename);
1190 cu_version = read_16 (ptr);
1191 if (cu_version != 2 && cu_version != 3)
1193 error (0, 0, "%s: DWARF version %d unhandled", dso->filename,
1198 value = read_32_relocated (ptr);
1199 if (value >= debug_sections[DEBUG_ABBREV].size)
1201 if (debug_sections[DEBUG_ABBREV].data == NULL)
1202 error (0, 0, "%s: .debug_abbrev not present", dso->filename);
1204 error (0, 0, "%s: DWARF CU abbrev offset too large",
1211 ptr_size = read_1 (ptr);
1212 if (ptr_size != 4 && ptr_size != 8)
1214 error (0, 0, "%s: Invalid DWARF pointer size %d",
1215 dso->filename, ptr_size);
1219 else if (read_1 (ptr) != ptr_size)
1221 error (0, 0, "%s: DWARF pointer size differs between CUs",
1226 abbrev = read_abbrev (dso,
1227 debug_sections[DEBUG_ABBREV].data + value);
1233 tag.entry = read_uleb128 (ptr);
1236 t = htab_find_with_hash (abbrev, &tag, tag.entry);
1239 error (0, 0, "%s: Could not find DWARF abbreviation %d",
1240 dso->filename, tag.entry);
1241 htab_delete (abbrev);
1245 ptr = edit_attributes (dso, ptr, t, phase);
1250 htab_delete (abbrev);
1259 static struct poptOption optionsTable[] = {
1260 { "base-dir", 'b', POPT_ARG_STRING, &base_dir, 0,
1261 "base build directory of objects", NULL },
1262 { "dest-dir", 'd', POPT_ARG_STRING, &dest_dir, 0,
1263 "directory to rewrite base-dir into", NULL },
1264 { "list-file", 'l', POPT_ARG_STRING, &list_file, 0,
1265 "file where to put list of source and header file names", NULL },
1266 { "build-id", 'i', POPT_ARG_NONE, &do_build_id, 0,
1267 "recompute build ID note and print ID on stdout", NULL },
1269 { NULL, 0, 0, NULL, 0, NULL, NULL }
1273 fdopen_dso (int fd, const char *name)
1280 elf = elf_begin (fd, ELF_C_RDWR_MMAP, NULL);
1283 error (0, 0, "cannot open ELF file: %s", elf_errmsg (-1));
1287 if (elf_kind (elf) != ELF_K_ELF)
1289 error (0, 0, "\"%s\" is not an ELF file", name);
1293 if (gelf_getehdr (elf, &ehdr) == NULL)
1295 error (0, 0, "cannot get the ELF header: %s",
1300 if (ehdr.e_type != ET_DYN && ehdr.e_type != ET_EXEC && ehdr.e_type != ET_REL)
1302 error (0, 0, "\"%s\" is not a shared library", name);
1306 /* Allocate DSO structure. Leave place for additional 20 new section
1309 malloc (sizeof(DSO) + (ehdr.e_shnum + 20) * sizeof(GElf_Shdr)
1310 + (ehdr.e_shnum + 20) * sizeof(Elf_Scn *));
1313 error (0, ENOMEM, "Could not open DSO");
1317 elf_flagelf (elf, ELF_C_SET, ELF_F_LAYOUT);
1319 memset (dso, 0, sizeof(DSO));
1322 dso->scn = (Elf_Scn **) &dso->shdr[ehdr.e_shnum + 20];
1324 for (i = 0; i < ehdr.e_shnum; ++i)
1326 dso->scn[i] = elf_getscn (elf, i);
1327 gelf_getshdr (dso->scn[i], dso->shdr + i);
1330 dso->filename = (const char *) strdup (name);
1336 free ((char *) dso->filename);
1346 static const pgpHashAlgo algorithms[] = { PGPHASHALGO_MD5,
1347 PGPHASHALGO_SHA1, PGPHASHALGO_SHA256, PGPHASHALGO_SHA384, PGPHASHALGO_SHA512 };
1349 /* Compute a fresh build ID bit-string from the editted file contents. */
1351 handle_build_id (DSO *dso, Elf_Data *build_id,
1352 size_t build_id_offset, size_t build_id_size)
1355 pgpHashAlgo algorithm;
1356 int i = sizeof(algorithms)/sizeof(algorithms[0]);
1357 void *digest = NULL;
1362 algorithm = algorithms[i];
1363 if (rpmDigestLength(algorithm) == build_id_size)
1368 fprintf (stderr, "Cannot handle %Zu-byte build ID\n", build_id_size);
1375 if (elf_update (dso->elf, ELF_C_NULL) < 0)
1377 fprintf (stderr, "Failed to update file: %s\n",
1378 elf_errmsg (elf_errno ()));
1382 /* Clear the old bits so they do not affect the new hash. */
1383 memset ((char *) build_id->d_buf + build_id_offset, 0, build_id_size);
1385 ctx = rpmDigestInit(algorithm, 0);
1387 /* Slurp the relevant header bits and section contents and feed them
1388 into the hash function. The only bits we ignore are the offset
1389 fields in ehdr and shdrs, since the semantically identical ELF file
1390 could be written differently if it doesn't change the phdr layout.
1391 We always use the GElf (i.e. Elf64) formats for the bits to hash
1392 since it is convenient. It doesn't matter whether this is an Elf32
1393 or Elf64 object, only that we are consistent in what bits feed the
1394 hash so it comes out the same for the same file contents. */
1402 Elf_Data x = { .d_version = EV_CURRENT, .d_buf = &u };
1404 x.d_type = ELF_T_EHDR;
1405 x.d_size = sizeof u.ehdr;
1407 u.ehdr.e_phoff = u.ehdr.e_shoff = 0;
1408 if (elf64_xlatetom (&x, &x, dso->ehdr.e_ident[EI_DATA]) == NULL)
1411 fprintf (stderr, "Failed to compute header checksum: %s\n",
1412 elf_errmsg (elf_errno ()));
1416 x.d_type = ELF_T_PHDR;
1417 x.d_size = sizeof u.phdr;
1418 for (i = 0; i < dso->ehdr.e_phnum; ++i)
1420 if (gelf_getphdr (dso->elf, i, &u.phdr) == NULL)
1422 if (elf64_xlatetom (&x, &x, dso->ehdr.e_ident[EI_DATA]) == NULL)
1424 rpmDigestUpdate(ctx, x.d_buf, x.d_size);
1427 x.d_type = ELF_T_SHDR;
1428 x.d_size = sizeof u.shdr;
1429 for (i = 0; i < dso->ehdr.e_shnum; ++i)
1430 if (dso->scn[i] != NULL)
1432 u.shdr = dso->shdr[i];
1433 u.shdr.sh_offset = 0;
1434 if (elf64_xlatetom (&x, &x, dso->ehdr.e_ident[EI_DATA]) == NULL)
1436 rpmDigestUpdate(ctx, x.d_buf, x.d_size);
1438 if (u.shdr.sh_type != SHT_NOBITS)
1440 Elf_Data *d = elf_rawdata (dso->scn[i], NULL);
1443 rpmDigestUpdate(ctx, d->d_buf, d->d_size);
1448 rpmDigestFinal(ctx, &digest, &len, 0);
1449 memcpy((unsigned char *)build_id->d_buf + build_id_offset, digest, build_id_size);
1452 elf_flagdata (build_id, ELF_C_SET, ELF_F_DIRTY);
1455 /* Now format the build ID bits in hex to print out. */
1457 const uint8_t * id = (uint8_t *)build_id->d_buf + build_id_offset;
1458 char *hex = pgpHexStr(id, build_id_size);
1465 main (int argc, char *argv[])
1470 poptContext optCon; /* context for parsing command-line options */
1473 struct stat stat_buf;
1475 Elf_Data *build_id = NULL;
1476 size_t build_id_offset = 0, build_id_size = 0;
1478 optCon = poptGetContext("debugedit", argc, (const char **)argv, optionsTable, 0);
1480 while ((nextopt = poptGetNextOpt (optCon)) > 0 || nextopt == POPT_ERROR_BADOPT)
1485 fprintf (stderr, "Error on option %s: %s.\nRun '%s --help' to see a full list of available command line options.\n",
1486 poptBadOption (optCon, 0),
1487 poptStrerror (nextopt),
1492 args = poptGetArgs (optCon);
1493 if (args == NULL || args[0] == NULL || args[1] != NULL)
1495 poptPrintHelp(optCon, stdout, 0);
1499 if (dest_dir != NULL)
1501 if (base_dir == NULL)
1503 fprintf (stderr, "You must specify a base dir if you specify a dest dir\n");
1506 if (strlen (dest_dir) > strlen (base_dir))
1508 fprintf (stderr, "Dest dir longer than base dir is not supported\n");
1513 /* Make sure there are trailing slashes in dirs */
1514 if (base_dir != NULL && base_dir[strlen (base_dir)-1] != '/')
1516 p = malloc (strlen (base_dir) + 2);
1517 strcpy (p, base_dir);
1522 if (dest_dir != NULL && dest_dir[strlen (dest_dir)-1] != '/')
1524 p = malloc (strlen (dest_dir) + 2);
1525 strcpy (p, dest_dir);
1531 if (list_file != NULL)
1533 list_file_fd = open (list_file, O_WRONLY|O_CREAT|O_APPEND, 0644);
1538 if (elf_version(EV_CURRENT) == EV_NONE)
1540 fprintf (stderr, "library out of date\n");
1544 if (stat(file, &stat_buf) < 0)
1546 fprintf (stderr, "Failed to open input file '%s': %s\n", file, strerror(errno));
1550 /* Make sure we can read and write */
1551 chmod (file, stat_buf.st_mode | S_IRUSR | S_IWUSR);
1553 fd = open (file, O_RDWR);
1556 fprintf (stderr, "Failed to open input file '%s': %s\n", file, strerror(errno));
1560 dso = fdopen_dso (fd, file);
1564 for (i = 1; i < dso->ehdr.e_shnum; i++)
1568 switch (dso->shdr[i].sh_type)
1571 name = strptr (dso, dso->ehdr.e_shstrndx, dso->shdr[i].sh_name);
1572 /* TODO: Handle stabs */
1574 if (strcmp (name, ".stab") == 0)
1575 edit_stabs (dso, i);
1577 if (strcmp (name, ".debug_info") == 0)
1583 && build_id == NULL && (dso->shdr[i].sh_flags & SHF_ALLOC))
1585 /* Look for a build-ID note here. */
1586 Elf_Data *data = elf_rawdata (elf_getscn (dso->elf, i), NULL);
1590 .d_version = EV_CURRENT, .d_type = ELF_T_NHDR,
1591 .d_buf = &nh, .d_size = sizeof nh
1594 src.d_buf = data->d_buf;
1595 assert (sizeof (Elf32_Nhdr) == sizeof (Elf64_Nhdr));
1596 while ((char *) data->d_buf + data->d_size -
1597 (char *) src.d_buf > (int) sizeof nh
1598 && elf32_xlatetom (&dst, &src, dso->ehdr.e_ident[EI_DATA]))
1600 Elf32_Word len = sizeof nh + nh.n_namesz;
1601 len = (len + 3) & ~3;
1603 if (nh.n_namesz == sizeof "GNU" && nh.n_type == 3
1604 && !memcmp ((char *) src.d_buf + sizeof nh, "GNU", sizeof "GNU"))
1607 build_id_offset = (char *) src.d_buf + len -
1608 (char *) data->d_buf;
1609 build_id_size = nh.n_descsz;
1614 len = (len + 3) & ~3;
1615 src.d_buf = (char *) src.d_buf + len;
1624 if (do_build_id && build_id != NULL)
1625 handle_build_id (dso, build_id, build_id_offset, build_id_size);
1627 if (elf_update (dso->elf, ELF_C_WRITE) < 0)
1629 fprintf (stderr, "Failed to write file: %s\n", elf_errmsg (elf_errno()));
1632 if (elf_end (dso->elf) < 0)
1634 fprintf (stderr, "elf_end failed: %s\n", elf_errmsg (elf_errno()));
1639 /* Restore old access rights */
1640 chmod (file, stat_buf.st_mode);
1642 poptFreeContext (optCon);