1 /* Copyright (C) 2001, 2002 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. */
19 /* Needed for libelf */
20 #define _FILE_OFFSET_BITS 64
31 #include <sys/types.h>
41 char *base_dir = NULL;
42 char *dest_dir = NULL;
43 char *list_file = NULL;
44 int list_file_fd = -1;
46 typedef unsigned int uint_32;
47 typedef unsigned short uint_16;
60 #define read_uleb128(ptr) ({ \
61 unsigned int ret = 0; \
67 ret |= (c & 0x7f) << shift; \
76 static uint_16 (*do_read_16) (unsigned char *ptr);
77 static uint_32 (*do_read_32) (unsigned char *ptr);
78 static void (*write_32) (unsigned char *ptr, GElf_Addr val);
83 buf_read_ule16 (unsigned char *data)
85 return data[0] | (data[1] << 8);
89 buf_read_ube16 (unsigned char *data)
91 return data[1] | (data[0] << 8);
95 buf_read_ule32 (unsigned char *data)
97 return data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
100 static inline uint_32
101 buf_read_ube32 (unsigned char *data)
103 return data[3] | (data[2] << 8) | (data[1] << 16) | (data[0] << 24);
107 strptr (DSO *dso, int sec, off_t offset)
113 if (offset >= 0 && offset < dso->shdr[sec].sh_size)
116 while ((data = elf_rawdata (scn, data)) != NULL)
119 && offset >= data->d_off
120 && offset < data->d_off + data->d_size)
121 return (const char *) data->d_buf + (offset - data->d_off);
129 #define read_1(ptr) *ptr++
131 #define read_16(ptr) ({ \
132 uint_16 ret = do_read_16 (ptr); \
137 #define read_32(ptr) ({ \
138 uint_32 ret = do_read_32 (ptr); \
144 dwarf2_write_le32 (unsigned char *p, GElf_Addr val)
146 uint_32 v = (uint_32) val;
156 dwarf2_write_be32 (unsigned char *p, GElf_Addr val)
158 uint_32 v = (uint_32) val;
176 #define DEBUG_ABBREV 1
178 #define DEBUG_ARANGES 3
179 #define DEBUG_PUBNAMES 4
180 #define DEBUG_MACINFO 5
183 #define DEBUG_FRAME 8
184 #define DEBUG_RANGES 9
185 { ".debug_info", NULL, 0, 0 },
186 { ".debug_abbrev", NULL, 0, 0 },
187 { ".debug_line", NULL, 0, 0 },
188 { ".debug_aranges", NULL, 0, 0 },
189 { ".debug_pubnames", NULL, 0, 0 },
190 { ".debug_macinfo", NULL, 0, 0 },
191 { ".debug_loc", NULL, 0, 0 },
192 { ".debug_str", NULL, 0, 0 },
193 { ".debug_frame", NULL, 0, 0 },
194 { ".debug_ranges", NULL, 0, 0 },
209 struct abbrev_attr attr[0];
213 abbrev_hash (const void *p)
215 struct abbrev_tag *t = (struct abbrev_tag *)p;
221 abbrev_eq (const void *p, const void *q)
223 struct abbrev_tag *t1 = (struct abbrev_tag *)p;
224 struct abbrev_tag *t2 = (struct abbrev_tag *)p;
226 return t1->entry == t2->entry;
236 read_abbrev (DSO *dso, unsigned char *ptr)
238 htab_t h = htab_try_create (50, abbrev_hash, abbrev_eq, abbrev_del);
239 unsigned int attr, form;
240 struct abbrev_tag *t;
247 error (0, ENOMEM, "%s: Could not read .debug_abbrev", dso->filename);
253 while ((attr = read_uleb128 (ptr)) != 0)
256 t = malloc (sizeof (*t) + size * sizeof (struct abbrev_attr));
261 slot = htab_find_slot (h, t, INSERT);
269 error (0, 0, "%s: Duplicate DWARF-2 abbreviation %d", dso->filename,
275 t->tag = read_uleb128 (ptr);
276 ++ptr; /* skip children flag. */
277 while ((attr = read_uleb128 (ptr)) != 0)
279 if (t->nattr == size)
282 t = realloc (t, sizeof (*t) + size * sizeof (struct abbrev_attr));
286 form = read_uleb128 (ptr);
287 if (form == 2 || form > DW_FORM_indirect)
289 error (0, 0, "%s: Unknown DWARF-2 DW_FORM_%d", dso->filename, form);
294 t->attr[t->nattr].attr = attr;
295 t->attr[t->nattr++].form = form;
297 if (read_uleb128 (ptr) != 0)
299 error (0, 0, "%s: DWARF-2 abbreviation does not end with 2 zeros",
310 #define IS_DIR_SEPARATOR(c) ((c)=='/')
313 canonicalize_path (char *s, char *d)
321 if (IS_DIR_SEPARATOR (*s))
324 if (IS_DIR_SEPARATOR (*s) && !IS_DIR_SEPARATOR (s[1]))
326 /* Special case for "//foo" meaning a Posix namespace
330 while (IS_DIR_SEPARATOR (*s))
338 /* At this point, we're always at the beginning of a path
341 if (s[0] == '.' && (s[1] == 0 || IS_DIR_SEPARATOR (s[1])))
350 else if (s[0] == '.' && s[1] == '.'
351 && (s[2] == 0 || IS_DIR_SEPARATOR (s[2])))
353 char *pre = d-1; /* includes slash */
354 while (droot < pre && IS_DIR_SEPARATOR (*pre))
356 if (droot <= pre && ! IS_DIR_SEPARATOR (*pre))
359 while (droot < d && ! IS_DIR_SEPARATOR (*d))
361 /* d now points to the slash */
381 while (*s && ! IS_DIR_SEPARATOR (*s))
385 if (IS_DIR_SEPARATOR (*s))
388 while (IS_DIR_SEPARATOR (*s))
392 while (droot < d && IS_DIR_SEPARATOR (d[-1]))
402 has_prefix (const char *str,
408 str_len = strlen (str);
409 prefix_len = strlen (prefix);
411 if (str_len < prefix_len)
414 return strncmp (str, prefix, prefix_len) == 0;
418 edit_dwarf2_line (DSO *dso, uint_32 off, char *comp_dir, int phase)
420 unsigned char *ptr = debug_sections[DEBUG_LINE].data;
421 unsigned char *endsec = ptr + debug_sections[DEBUG_LINE].size;
422 unsigned char *endcu, *endprol;
423 unsigned char opcode_base;
435 endcu += read_32 (ptr);
436 if (endcu == ptr + 0xffffffff)
438 error (0, 0, "%s: 64-bit DWARF not supported", dso->filename);
444 error (0, 0, "%s: .debug_line CU does not fit into section",
449 value = read_16 (ptr);
452 error (0, 0, "%s: DWARF version %d unhandled", dso->filename,
458 endprol += read_32 (ptr);
461 error (0, 0, "%s: .debug_line CU prologue does not fit into CU",
466 opcode_base = ptr[4];
467 ptr = ptr + 4 + opcode_base;
472 ptr = strchr(ptr, 0) + 1;
486 s = malloc (strlen (comp_dir) + 1 + strlen (ptr) + 1);
487 strcpy (s, comp_dir);
490 canonicalize_path (s, s);
492 if (base_dir == NULL ||
493 has_prefix (s, base_dir))
499 p = s + strlen (base_dir);
503 if (list_file_fd != -1)
505 size = strlen (p) + 1;
508 ret = write (list_file_fd, p, size);
521 ptr = strchr(ptr, 0) + 1;
532 static unsigned char *
533 edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase)
538 unsigned char *comp_dir;
543 for (i = 0; i < t->nattr; ++i)
545 uint_32 form = t->attr[i].form;
547 int base_len, dest_len;
552 if (t->attr[i].attr == DW_AT_stmt_list)
554 if (form == DW_FORM_data4)
556 list_offs = do_read_32 (ptr);
561 if (debug_sections[DEBUG_STR].data &&
562 t->attr[i].attr == DW_AT_comp_dir &&
563 form == DW_FORM_strp)
567 dir = debug_sections[DEBUG_STR].data + do_read_32 (ptr);
568 comp_dir = strdup (dir);
570 if (phase == 1 && dest_dir && has_prefix (dir, base_dir))
572 base_len = strlen (base_dir);
573 dest_len = strlen (dest_dir);
575 memcpy (dir, dest_dir, dest_len);
576 if (dest_len < base_len)
578 memcpy (dir + dest_len, dir + base_len,
579 strlen (dir + base_len) + 1);
581 elf_flagdata (debug_sections[DEBUG_STR].elf_data,
582 ELF_C_SET, ELF_F_DIRTY);
609 case DW_FORM_ref_udata:
613 case DW_FORM_ref_addr:
618 ptr = strchr (ptr, '\0') + 1;
620 case DW_FORM_indirect:
621 form = read_uleb128 (ptr);
628 form = DW_FORM_block1;
632 form = DW_FORM_block1;
635 len = read_uleb128 (ptr);
636 form = DW_FORM_block1;
637 assert (len < UINT_MAX);
640 error (0, 0, "%s: Unknown DWARF-2 DW_FORM_%d", dso->filename,
645 if (form == DW_FORM_block1)
651 if (found_list_offs && comp_dir)
652 edit_dwarf2_line (dso, list_offs, comp_dir, phase);
658 edit_dwarf2 (DSO *dso, int n)
664 for (i = 0; debug_sections[i].name; ++i)
666 debug_sections[i].data = NULL;
667 debug_sections[i].size = 0;
668 debug_sections[i].sec = 0;
672 for (i = 1; i < dso->ehdr.e_shnum; ++i)
673 if (! (dso->shdr[i].sh_flags & (SHF_ALLOC | SHF_WRITE | SHF_EXECINSTR))
674 && dso->shdr[i].sh_size)
676 const char *name = strptr (dso, dso->ehdr.e_shstrndx,
677 dso->shdr[i].sh_name);
679 if (strncmp (name, ".debug_", sizeof (".debug_") - 1) == 0)
681 for (j = 0; debug_sections[j].name; ++j)
682 if (strcmp (name, debug_sections[j].name) == 0)
684 if (debug_sections[j].data)
686 error (0, 0, "%s: Found two copies of %s section",
687 dso->filename, name);
692 data = elf_rawdata (scn, NULL);
693 assert (data != NULL && data->d_buf != NULL);
694 assert (elf_rawdata (scn, data) == NULL);
695 assert (data->d_off == 0);
696 assert (data->d_size == dso->shdr[i].sh_size);
697 debug_sections[j].data = data->d_buf;
698 debug_sections[j].elf_data = data;
699 debug_sections[j].size = data->d_size;
700 debug_sections[j].sec = i;
704 if (debug_sections[j].name == NULL)
706 error (0, 0, "%s: Unknown debugging section %s",
707 dso->filename, name);
712 if (dso->ehdr.e_ident[EI_DATA] == ELFDATA2LSB)
714 do_read_16 = buf_read_ule16;
715 do_read_32 = buf_read_ule32;
716 write_32 = dwarf2_write_le32;
718 else if (dso->ehdr.e_ident[EI_DATA] == ELFDATA2MSB)
720 do_read_16 = buf_read_ube16;
721 do_read_32 = buf_read_ube32;
722 write_32 = dwarf2_write_be32;
726 error (0, 0, "%s: Wrong ELF data enconding", dso->filename);
730 if (debug_sections[DEBUG_INFO].data != NULL)
732 unsigned char *ptr, *endcu, *endsec;
735 struct abbrev_tag tag, *t;
738 for (phase = 0; phase < 2; phase++)
740 ptr = debug_sections[DEBUG_INFO].data;
741 endsec = ptr + debug_sections[DEBUG_INFO].size;
744 if (ptr + 11 > endsec)
746 error (0, 0, "%s: .debug_info CU header too small",
752 endcu += read_32 (ptr);
753 if (endcu == ptr + 0xffffffff)
755 error (0, 0, "%s: 64-bit DWARF not supported", dso->filename);
761 error (0, 0, "%s: .debug_info too small", dso->filename);
765 value = read_16 (ptr);
768 error (0, 0, "%s: DWARF version %d unhandled", dso->filename,
773 value = read_32 (ptr);
774 if (value >= debug_sections[DEBUG_ABBREV].size)
776 if (debug_sections[DEBUG_ABBREV].data == NULL)
777 error (0, 0, "%s: .debug_abbrev not present", dso->filename);
779 error (0, 0, "%s: DWARF-2 CU abbrev offset too large",
786 ptr_size = read_1 (ptr);
787 if (ptr_size != 4 && ptr_size != 8)
789 error (0, 0, "%s: Invalid DWARF-2 pointer size %d",
790 dso->filename, ptr_size);
794 else if (read_1 (ptr) != ptr_size)
796 error (0, 0, "%s: DWARF-2 pointer size differs between CUs",
801 abbrev = read_abbrev (dso,
802 debug_sections[DEBUG_ABBREV].data + value);
808 tag.entry = read_uleb128 (ptr);
811 t = htab_find_with_hash (abbrev, &tag, tag.entry);
814 error (0, 0, "%s: Could not find DWARF-2 abbreviation %d",
815 dso->filename, tag.entry);
816 htab_delete (abbrev);
820 ptr = edit_attributes (dso, ptr, t, phase);
825 htab_delete (abbrev);
833 static struct poptOption optionsTable[] = {
834 { "base-dir", 'b', POPT_ARG_STRING, &base_dir, 0,
835 "base build directory of objects", NULL },
836 { "dest-dir", 'd', POPT_ARG_STRING, &dest_dir, 0,
837 "directory to rewrite base-dir into", NULL },
838 { "list-file", 'l', POPT_ARG_STRING, &list_file, 0,
839 "directory to rewrite base-dir into", NULL },
841 { NULL, 0, 0, NULL, 0 }
845 fdopen_dso (int fd, const char *name)
852 elf = elf_begin (fd, ELF_C_RDWR_MMAP, NULL);
855 error (0, 0, "cannot open ELF file: %s", elf_errmsg (-1));
859 if (elf_kind (elf) != ELF_K_ELF)
861 error (0, 0, "\"%s\" is not an ELF file", name);
865 if (gelf_getehdr (elf, &ehdr) == NULL)
867 error (0, 0, "cannot get the ELF header: %s",
872 if (ehdr.e_type != ET_DYN && ehdr.e_type != ET_EXEC)
874 error (0, 0, "\"%s\" is not a shared library", name);
878 /* Allocate DSO structure. Leave place for additional 20 new section
881 malloc (sizeof(DSO) + (ehdr.e_shnum + 20) * sizeof(GElf_Shdr)
882 + (ehdr.e_phnum + 1) * sizeof(GElf_Phdr)
883 + (ehdr.e_shnum + 20) * sizeof(Elf_Scn *));
886 error (0, ENOMEM, "Could not open DSO");
890 elf_flagelf (elf, ELF_C_SET, ELF_F_LAYOUT);
892 memset (dso, 0, sizeof(DSO));
895 dso->phdr = (GElf_Phdr *) &dso->shdr[ehdr.e_shnum + 20];
896 dso->scn = (Elf_Scn **) &dso->phdr[ehdr.e_phnum + 1];
897 for (i = 0; i < ehdr.e_phnum; ++i)
898 gelf_getphdr (elf, i, dso->phdr + i);
900 for (i = 0; i < ehdr.e_shnum; ++i)
902 dso->scn[i] = elf_getscn (elf, i);
903 gelf_getshdr (dso->scn[i], dso->shdr + i);
906 dso->filename = (const char *) strdup (name);
912 free ((char *) dso->filename);
924 main (int argc, char *argv[])
929 poptContext optCon; /* context for parsing command-line options */
932 struct stat stat_buf;
935 optCon = poptGetContext("debugedit", argc, (const char **)argv,
938 while ((nextopt = poptGetNextOpt (optCon)) > 0 || nextopt == POPT_ERROR_BADOPT)
943 fprintf (stderr, "Error on option %s: %s.\nRun '%s --help' to see a full list of available command line options.\n",
944 poptBadOption (optCon, 0),
945 poptStrerror (nextopt),
950 args = poptGetArgs (optCon);
951 if (args == NULL || args[0] == NULL || args[1] != NULL)
953 poptPrintHelp(optCon, stdout, 0);
957 if (dest_dir != NULL)
959 if (base_dir == NULL)
961 fprintf (stderr, "You must specify a base dir if you specify a dest dir\n");
964 if (strlen (dest_dir) > strlen (base_dir))
966 fprintf (stderr, "Only dest dir longer than base dir not supported\n");
971 /* Make sure there are trailing slashes in dirs */
972 if (base_dir != NULL && base_dir[strlen (base_dir)-1] != '/')
974 p = malloc (strlen (base_dir) + 2);
975 strcpy (p, base_dir);
980 if (dest_dir != NULL && dest_dir[strlen (dest_dir)-1] != '/')
982 p = malloc (strlen (dest_dir) + 2);
983 strcpy (p, dest_dir);
989 if (list_file != NULL)
991 list_file_fd = open (list_file, O_WRONLY|O_CREAT|O_APPEND, 0644);
996 if (elf_version(EV_CURRENT) == EV_NONE)
998 fprintf (stderr, "library out of date\n");
1002 if (stat(file, &stat_buf) < 0)
1004 fprintf (stderr, "Failed to open input file '%s': %s\n", file, strerror(errno));
1008 /* Make sure we can read and write */
1009 chmod (file, stat_buf.st_mode | S_IRUSR | S_IWUSR);
1011 fd = open (file, O_RDWR);
1014 fprintf (stderr, "Failed to open input file '%s': %s\n", file, strerror(errno));
1018 dso = fdopen_dso (fd, file);
1020 for (i = 1; i < dso->ehdr.e_shnum; i++)
1024 switch (dso->shdr[i].sh_type)
1027 name = strptr (dso, dso->ehdr.e_shstrndx, dso->shdr[i].sh_name);
1028 /* TODO: Handle stabs */
1030 if (strcmp (name, ".stab") == 0)
1031 edit_stabs (dso, i);
1033 if (strcmp (name, ".debug_info") == 0)
1034 edit_dwarf2 (dso, i);
1042 if (elf_update (dso->elf, ELF_C_WRITE) < 0)
1044 fprintf (stderr, "Failed to write file: %s\n", elf_errmsg (elf_errno()));
1047 if (elf_end (dso->elf) < 0)
1049 fprintf (stderr, "elf_end failed: %s\n", elf_errmsg (elf_errno()));
1054 /* Restore old access rights */
1055 chmod (file, stat_buf.st_mode);
1057 poptFreeContext (optCon);