]>
git.ipfire.org Git - pakfire.git/blob - src/debugedit/debugedit.c
75b48f0b9a0eb27310902a270aefc5c7bf901eb3
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.
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>
38 /* some defines taken from the dwarf standard */
40 #define DW_TAG_compile_unit 0x11
42 #define DW_AT_name 0x03
43 #define DW_AT_stmt_list 0x10
44 #define DW_AT_comp_dir 0x1b
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
68 #include <beecrypt/beecrypt.h>
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
78 char *base_dir
= NULL
;
79 char *dest_dir
= NULL
;
80 char *list_file
= NULL
;
81 int list_file_fd
= -1;
100 #define read_uleb128(ptr) ({ \
101 unsigned int ret = 0; \
107 ret |= (c & 0x7f) << shift; \
109 } while (c & 0x80); \
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
);
121 static int cu_version
;
123 static inline rpmuint16_t
124 buf_read_ule16 (unsigned char *data
)
126 return data
[0] | (data
[1] << 8);
129 static inline rpmuint16_t
130 buf_read_ube16 (unsigned char *data
)
132 return data
[1] | (data
[0] << 8);
135 static inline rpmuint32_t
136 buf_read_ule32 (unsigned char *data
)
138 return data
[0] | (data
[1] << 8) | (data
[2] << 16) | (data
[3] << 24);
141 static inline rpmuint32_t
142 buf_read_ube32 (unsigned char *data
)
144 return data
[3] | (data
[2] << 8) | (data
[1] << 16) | (data
[0] << 24);
148 strptr (DSO
*dso
, int sec
, off_t offset
)
154 if (offset
>= 0 && (GElf_Addr
) offset
< dso
->shdr
[sec
].sh_size
)
157 while ((data
= elf_rawdata (scn
, data
)) != NULL
)
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
);
170 #define read_1(ptr) *ptr++
172 #define read_16(ptr) ({ \
173 rpmuint16_t ret = do_read_16 (ptr); \
178 #define read_32(ptr) ({ \
179 rpmuint32_t ret = do_read_32 (ptr); \
184 REL
*relptr
, *relend
;
187 #define do_read_32_relocated(ptr) ({ \
188 rpmuint32_t dret = do_read_32 (ptr); \
191 while (relptr < relend && relptr->ptr < ptr) \
193 if (relptr < relend && relptr->ptr == ptr) \
195 if (reltype == SHT_REL) \
196 dret += relptr->addend; \
198 dret = relptr->addend; \
204 #define read_32_relocated(ptr) ({ \
205 rpmuint32_t ret = do_read_32_relocated (ptr); \
211 dwarf2_write_le32 (unsigned char *p
, GElf_Addr val
)
213 rpmuint32_t v
= (rpmuint32_t
) val
;
223 dwarf2_write_be32 (unsigned char *p
, GElf_Addr val
)
225 rpmuint32_t v
= (rpmuint32_t
) val
;
243 #define DEBUG_ABBREV 1
245 #define DEBUG_ARANGES 3
246 #define DEBUG_PUBNAMES 4
247 #define DEBUG_PUBTYPES 5
248 #define DEBUG_MACINFO 6
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 }
282 struct abbrev_attr attr
[0];
286 abbrev_hash (const void *p
)
288 struct abbrev_tag
*t
= (struct abbrev_tag
*)p
;
294 abbrev_eq (const void *p
, const void *q
)
296 struct abbrev_tag
*t1
= (struct abbrev_tag
*)p
;
297 struct abbrev_tag
*t2
= (struct abbrev_tag
*)q
;
299 return t1
->entry
== t2
->entry
;
309 read_abbrev (DSO
*dso
, unsigned char *ptr
)
311 htab_t h
= htab_try_create (50, abbrev_hash
, abbrev_eq
, abbrev_del
);
312 unsigned int attr
, form
;
313 struct abbrev_tag
*t
;
320 error (0, ENOMEM
, "%s: Could not read .debug_abbrev", dso
->filename
);
326 while ((attr
= read_uleb128 (ptr
)) != 0)
329 t
= malloc (sizeof (*t
) + size
* sizeof (struct abbrev_attr
));
334 slot
= htab_find_slot (h
, t
, INSERT
);
342 error (0, 0, "%s: Duplicate DWARF abbreviation %d", dso
->filename
,
348 t
->tag
= read_uleb128 (ptr
);
349 ++ptr
; /* skip children flag. */
350 while ((attr
= read_uleb128 (ptr
)) != 0)
352 if (t
->nattr
== size
)
355 t
= realloc (t
, sizeof (*t
) + size
* sizeof (struct abbrev_attr
));
359 form
= read_uleb128 (ptr
);
361 || (form
> DW_FORM_flag_present
&& form
!= DW_FORM_ref_sig8
))
363 error (0, 0, "%s: Unknown DWARF DW_FORM_%d", dso
->filename
, form
);
368 t
->attr
[t
->nattr
].attr
= attr
;
369 t
->attr
[t
->nattr
++].form
= form
;
371 if (read_uleb128 (ptr
) != 0)
373 error (0, 0, "%s: DWARF abbreviation does not end with 2 zeros",
384 #define IS_DIR_SEPARATOR(c) ((c)=='/')
387 canonicalize_path (const char *s
, char *d
)
393 if (IS_DIR_SEPARATOR (*s
))
396 if (IS_DIR_SEPARATOR (*s
) && !IS_DIR_SEPARATOR (s
[1]))
398 /* Special case for "//foo" meaning a Posix namespace
402 while (IS_DIR_SEPARATOR (*s
))
410 /* At this point, we're always at the beginning of a path
413 if (s
[0] == '.' && (s
[1] == 0 || IS_DIR_SEPARATOR (s
[1])))
417 while (IS_DIR_SEPARATOR (*s
))
421 else if (s
[0] == '.' && s
[1] == '.'
422 && (s
[2] == 0 || IS_DIR_SEPARATOR (s
[2])))
424 char *pre
= d
- 1; /* includes slash */
425 while (droot
< pre
&& IS_DIR_SEPARATOR (*pre
))
427 if (droot
<= pre
&& ! IS_DIR_SEPARATOR (*pre
))
429 while (droot
< pre
&& ! IS_DIR_SEPARATOR (*pre
))
431 /* pre now points to the slash */
434 if (pre
+ 3 == d
&& pre
[0] == '.' && pre
[1] == '.')
444 while (IS_DIR_SEPARATOR (*s
))
456 while (*s
&& ! IS_DIR_SEPARATOR (*s
))
460 if (IS_DIR_SEPARATOR (*s
))
463 while (IS_DIR_SEPARATOR (*s
))
467 while (droot
< d
&& IS_DIR_SEPARATOR (d
[-1]))
477 has_prefix (const char *str
,
483 str_len
= strlen (str
);
484 prefix_len
= strlen (prefix
);
486 if (str_len
< prefix_len
)
489 return strncmp (str
, prefix
, prefix_len
) == 0;
493 edit_dwarf2_line (DSO
*dso
, rpmuint32_t off
, char *comp_dir
, int phase
)
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;
510 endcu
+= read_32 (ptr
);
511 if (endcu
== ptr
+ 0xffffffff)
513 error (0, 0, "%s: 64-bit DWARF not supported", dso
->filename
);
519 error (0, 0, "%s: .debug_line CU does not fit into section",
524 value
= read_16 (ptr
);
525 if (value
!= 2 && value
!= 3 && value
!= 4)
527 error (0, 0, "%s: DWARF version %d unhandled", dso
->filename
,
533 endprol
+= read_32 (ptr
);
536 error (0, 0, "%s: .debug_line CU prologue does not fit into CU",
541 opcode_base
= ptr
[4 + (value
>= 4)];
542 ptr
= dir
= ptr
+ 4 + (value
>= 4) + opcode_base
;
548 ptr
= (unsigned char *) strchr ((char *)ptr
, 0) + 1;
552 dirt
= (unsigned char **) alloca (value
* sizeof (unsigned char *));
553 dirt
[0] = (unsigned char *) ".";
558 dirt
[dirt_cnt
++] = ptr
;
559 ptr
= (unsigned char *) strchr ((char *)ptr
, 0) + 1;
567 size_t file_len
, dir_len
;
570 ptr
= (unsigned char *) strchr ((char *)ptr
, 0) + 1;
571 value
= read_uleb128 (ptr
);
573 if (value
>= dirt_cnt
)
575 error (0, 0, "%s: Wrong directory table index %u",
576 dso
->filename
, value
);
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);
584 error (0, ENOMEM
, "%s: Reading file table", dso
->filename
);
589 memcpy (s
, file
, file_len
+ 1);
590 if (dest_dir
&& has_prefix (file
, base_dir
))
593 else if (*dirt
[value
] == '/')
595 memcpy (s
, dirt
[value
], dir_len
);
597 memcpy (s
+ dir_len
+ 1, file
, file_len
+ 1);
602 if (comp_dir_len
!= 0)
604 memcpy (s
, comp_dir
, comp_dir_len
);
605 s
[comp_dir_len
] = '/';
606 p
+= comp_dir_len
+ 1;
608 memcpy (p
, dirt
[value
], dir_len
);
610 memcpy (p
+ dir_len
+ 1, file
, file_len
+ 1);
612 canonicalize_path (s
, s
);
613 if (list_file_fd
!= -1)
616 if (base_dir
== NULL
)
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
);
625 size_t size
= strlen (p
) + 1;
628 ssize_t ret
= write (list_file_fd
, p
, size
);
646 unsigned char *srcptr
, *buf
= NULL
;
647 size_t base_len
= strlen (base_dir
);
648 size_t dest_len
= strlen (dest_dir
);
651 if (dest_len
== base_len
)
655 srcptr
= buf
= malloc (ptr
- dir
);
656 memcpy (srcptr
, dir
, ptr
- dir
);
663 size_t len
= strlen ((char *)srcptr
) + 1;
664 const unsigned char *readptr
= srcptr
;
666 if (*srcptr
== '/' && has_prefix ((char *)srcptr
, base_dir
))
668 if (dest_len
< base_len
)
670 memcpy (ptr
, dest_dir
, dest_len
);
676 shrank
+= srcptr
- readptr
;
677 canonicalize_path ((char *)readptr
, (char *)ptr
);
678 len
= strlen ((char *)ptr
) + 1;
682 elf_flagdata (debug_sections
[DEBUG_STR
].elf_data
,
683 ELF_C_SET
, ELF_F_DIRTY
);
689 error (EXIT_FAILURE
, 0,
690 "canonicalization unexpectedly shrank by one character");
693 memset (ptr
, 'X', shrank
);
699 if (abs_dir_cnt
+ abs_file_cnt
!= 0)
701 size_t len
= (abs_dir_cnt
+ abs_file_cnt
) * (base_len
- dest_len
);
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);
714 size_t len
= strlen ((char *)srcptr
) + 1;
716 if (*srcptr
== '/' && has_prefix ((char *)srcptr
, base_dir
))
718 memcpy (ptr
, dest_dir
, dest_len
);
719 if (dest_len
< base_len
)
721 memmove (ptr
+ dest_len
, srcptr
+ base_len
,
723 ptr
+= dest_len
- base_len
;
725 elf_flagdata (debug_sections
[DEBUG_STR
].elf_data
,
726 ELF_C_SET
, ELF_F_DIRTY
);
728 else if (ptr
!= srcptr
)
729 memmove (ptr
, srcptr
, len
);
733 read_uleb128 (srcptr
);
734 read_uleb128 (srcptr
);
735 read_uleb128 (srcptr
);
737 memmove (ptr
, dir
, srcptr
- dir
);
748 static unsigned char *
749 edit_attributes (DSO
*dso
, unsigned char *ptr
, struct abbrev_tag
*t
, int phase
)
752 rpmuint32_t list_offs
;
759 for (i
= 0; i
< t
->nattr
; ++i
)
761 rpmuint32_t form
= t
->attr
[i
].form
;
763 size_t base_len
, dest_len
;
768 if (t
->attr
[i
].attr
== DW_AT_stmt_list
)
770 if (form
== DW_FORM_data4
771 || form
== DW_FORM_sec_offset
)
773 list_offs
= do_read_32_relocated (ptr
);
778 if (t
->attr
[i
].attr
== DW_AT_comp_dir
)
780 if ( form
== DW_FORM_string
)
783 comp_dir
= strdup ((char *)ptr
);
785 if (phase
== 1 && dest_dir
&& has_prefix ((char *)ptr
, base_dir
))
787 base_len
= strlen (base_dir
);
788 dest_len
= strlen (dest_dir
);
790 memcpy (ptr
, dest_dir
, dest_len
);
791 if (dest_len
< base_len
)
793 memset(ptr
+ dest_len
, '/',
794 base_len
- dest_len
);
797 elf_flagdata (debug_sections
[DEBUG_INFO
].elf_data
,
798 ELF_C_SET
, ELF_F_DIRTY
);
802 else if (form
== DW_FORM_strp
&&
803 debug_sections
[DEBUG_STR
].data
)
807 dir
= (char *) debug_sections
[DEBUG_STR
].data
808 + do_read_32_relocated (ptr
);
811 comp_dir
= strdup (dir
);
813 if (phase
== 1 && dest_dir
&& has_prefix (dir
, base_dir
))
815 base_len
= strlen (base_dir
);
816 dest_len
= strlen (dest_dir
);
818 memcpy (dir
, dest_dir
, dest_len
);
819 if (dest_len
< base_len
)
821 memmove (dir
+ dest_len
, dir
+ base_len
,
822 strlen (dir
+ base_len
) + 1);
824 elf_flagdata (debug_sections
[DEBUG_STR
].elf_data
,
825 ELF_C_SET
, ELF_F_DIRTY
);
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
)
837 name
= (char *) debug_sections
[DEBUG_STR
].data
838 + do_read_32_relocated (ptr
);
839 if (*name
== '/' && comp_dir
== NULL
)
841 char *enddir
= strrchr (name
, '/');
845 comp_dir
= malloc (enddir
- name
+ 1);
846 memcpy (comp_dir
, name
, enddir
- name
);
847 comp_dir
[enddir
- name
] = '\0';
850 comp_dir
= strdup ("/");
853 if (phase
== 1 && dest_dir
&& has_prefix (name
, base_dir
))
855 base_len
= strlen (base_dir
);
856 dest_len
= strlen (dest_dir
);
858 memcpy (name
, dest_dir
, dest_len
);
859 if (dest_len
< base_len
)
861 memmove (name
+ dest_len
, name
+ base_len
,
862 strlen (name
+ base_len
) + 1);
864 elf_flagdata (debug_sections
[DEBUG_STR
].elf_data
,
865 ELF_C_SET
, ELF_F_DIRTY
);
871 case DW_FORM_ref_addr
:
877 case DW_FORM_flag_present
:
893 case DW_FORM_sec_offset
:
898 case DW_FORM_ref_sig8
:
902 case DW_FORM_ref_udata
:
910 ptr
= (unsigned char *) strchr ((char *)ptr
, '\0') + 1;
912 case DW_FORM_indirect
:
913 form
= read_uleb128 (ptr
);
920 form
= DW_FORM_block1
;
924 form
= DW_FORM_block1
;
927 case DW_FORM_exprloc
:
928 len
= read_uleb128 (ptr
);
929 form
= DW_FORM_block1
;
930 assert (len
< UINT_MAX
);
933 error (0, 0, "%s: Unknown DWARF DW_FORM_%d", dso
->filename
,
938 if (form
== DW_FORM_block1
)
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)
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
);
961 size
= strlen (p
) + 1;
964 ssize_t ret
= write (list_file_fd
, p
, size
);
972 if (found_list_offs
&& comp_dir
)
973 edit_dwarf2_line (dso
, list_offs
, comp_dir
, phase
);
981 rel_cmp (const void *a
, const void *b
)
983 REL
*rela
= (REL
*) a
, *relb
= (REL
*) b
;
985 if (rela
->ptr
< relb
->ptr
)
988 if (rela
->ptr
> relb
->ptr
)
995 edit_dwarf2 (DSO
*dso
)
1001 for (i
= 0; debug_sections
[i
].name
; ++i
)
1003 debug_sections
[i
].data
= NULL
;
1004 debug_sections
[i
].size
= 0;
1005 debug_sections
[i
].sec
= 0;
1006 debug_sections
[i
].relsec
= 0;
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
)
1014 const char *name
= strptr (dso
, dso
->ehdr
.e_shstrndx
,
1015 dso
->shdr
[i
].sh_name
);
1017 if (strncmp (name
, ".debug_", sizeof (".debug_") - 1) == 0)
1019 for (j
= 0; debug_sections
[j
].name
; ++j
)
1020 if (strcmp (name
, debug_sections
[j
].name
) == 0)
1022 if (debug_sections
[j
].data
)
1024 error (0, 0, "%s: Found two copies of %s section",
1025 dso
->filename
, name
);
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
;
1042 if (debug_sections
[j
].name
== NULL
)
1044 error (0, 0, "%s: Unknown debugging section %s",
1045 dso
->filename
, name
);
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)))
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)
1061 debug_sections
[j
].relsec
= i
;
1067 if (dso
->ehdr
.e_ident
[EI_DATA
] == ELFDATA2LSB
)
1069 do_read_16
= buf_read_ule16
;
1070 do_read_32
= buf_read_ule32
;
1071 write_32
= dwarf2_write_le32
;
1073 else if (dso
->ehdr
.e_ident
[EI_DATA
] == ELFDATA2MSB
)
1075 do_read_16
= buf_read_ube16
;
1076 do_read_32
= buf_read_ube32
;
1077 write_32
= dwarf2_write_be32
;
1081 error (0, 0, "%s: Wrong ELF data enconding", dso
->filename
);
1085 if (debug_sections
[DEBUG_INFO
].data
!= NULL
)
1087 unsigned char *ptr
, *endcu
, *endsec
;
1090 struct abbrev_tag tag
, *t
;
1094 if (debug_sections
[DEBUG_INFO
].relsec
)
1100 GElf_Addr base
= dso
->shdr
[debug_sections
[DEBUG_INFO
].sec
].sh_addr
;
1101 Elf_Data
*symdata
= NULL
;
1104 i
= debug_sections
[DEBUG_INFO
].relsec
;
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
;
1115 error (1, errno
, "%s: Could not allocate memory", dso
->filename
);
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
)
1121 assert (symdata
->d_off
== 0);
1122 assert (symdata
->d_size
1123 == dso
->shdr
[dso
->shdr
[i
].sh_link
].sh_size
);
1125 for (ndx
= 0, relend
= relbuf
; ndx
< maxndx
; ++ndx
)
1127 if (dso
->shdr
[i
].sh_type
== SHT_REL
)
1129 gelf_getrel (data
, ndx
, &rel
);
1130 rela
.r_offset
= rel
.r_offset
;
1131 rela
.r_info
= rel
.r_info
;
1135 gelf_getrela (data
, ndx
, &rela
);
1136 gelf_getsym (symdata
, ELF64_R_SYM (rela
.r_info
), &sym
);
1137 /* Relocations against section symbols are uninteresting
1139 if (dso
->shdr
[i
].sh_type
== SHT_REL
&& sym
.st_value
== 0)
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
)
1147 rela
.r_addend
+= sym
.st_value
;
1148 rtype
= ELF64_R_TYPE (rela
.r_info
);
1149 switch (dso
->ehdr
.e_machine
)
1152 case EM_SPARC32PLUS
:
1154 if (rtype
!= R_SPARC_32
&& rtype
!= R_SPARC_UA32
)
1158 if (rtype
!= R_386_32
)
1163 if (rtype
!= R_PPC_ADDR32
&& rtype
!= R_PPC_UADDR32
)
1167 if (rtype
!= R_390_32
)
1171 if (rtype
!= R_IA64_SECREL32LSB
)
1175 if (rtype
!= R_X86_64_32
)
1179 if (rtype
!= R_ALPHA_REFLONG
)
1184 error (1, 0, "%s: Unhandled relocation %d in .debug_info section",
1185 dso
->filename
, rtype
);
1187 relend
->ptr
= debug_sections
[DEBUG_INFO
].data
1188 + (rela
.r_offset
- base
);
1189 relend
->addend
= rela
.r_addend
;
1192 if (relbuf
== relend
)
1199 qsort (relbuf
, relend
- relbuf
, sizeof (REL
), rel_cmp
);
1202 for (phase
= 0; phase
< 2; phase
++)
1204 ptr
= debug_sections
[DEBUG_INFO
].data
;
1206 endsec
= ptr
+ debug_sections
[DEBUG_INFO
].size
;
1207 while (ptr
< endsec
)
1209 if (ptr
+ 11 > endsec
)
1211 error (0, 0, "%s: .debug_info CU header too small",
1217 endcu
+= read_32 (ptr
);
1218 if (endcu
== ptr
+ 0xffffffff)
1220 error (0, 0, "%s: 64-bit DWARF not supported", dso
->filename
);
1226 error (0, 0, "%s: .debug_info too small", dso
->filename
);
1230 cu_version
= read_16 (ptr
);
1231 if (cu_version
!= 2 && cu_version
!= 3 && cu_version
!= 4)
1233 error (0, 0, "%s: DWARF version %d unhandled", dso
->filename
,
1238 value
= read_32_relocated (ptr
);
1239 if (value
>= debug_sections
[DEBUG_ABBREV
].size
)
1241 if (debug_sections
[DEBUG_ABBREV
].data
== NULL
)
1242 error (0, 0, "%s: .debug_abbrev not present", dso
->filename
);
1244 error (0, 0, "%s: DWARF CU abbrev offset too large",
1251 ptr_size
= read_1 (ptr
);
1252 if (ptr_size
!= 4 && ptr_size
!= 8)
1254 error (0, 0, "%s: Invalid DWARF pointer size %d",
1255 dso
->filename
, ptr_size
);
1259 else if (read_1 (ptr
) != ptr_size
)
1261 error (0, 0, "%s: DWARF pointer size differs between CUs",
1266 abbrev
= read_abbrev (dso
,
1267 debug_sections
[DEBUG_ABBREV
].data
+ value
);
1273 tag
.entry
= read_uleb128 (ptr
);
1276 t
= htab_find_with_hash (abbrev
, &tag
, tag
.entry
);
1279 error (0, 0, "%s: Could not find DWARF abbreviation %d",
1280 dso
->filename
, tag
.entry
);
1281 htab_delete (abbrev
);
1285 ptr
= edit_attributes (dso
, ptr
, t
, phase
);
1290 htab_delete (abbrev
);
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
},
1309 { NULL
, 0, 0, NULL
, 0, NULL
, NULL
}
1313 fdopen_dso (int fd
, const char *name
)
1320 elf
= elf_begin (fd
, ELF_C_RDWR_MMAP
, NULL
);
1323 error (0, 0, "cannot open ELF file: %s", elf_errmsg (-1));
1327 if (elf_kind (elf
) != ELF_K_ELF
)
1329 error (0, 0, "\"%s\" is not an ELF file", name
);
1333 if (gelf_getehdr (elf
, &ehdr
) == NULL
)
1335 error (0, 0, "cannot get the ELF header: %s",
1340 if (ehdr
.e_type
!= ET_DYN
&& ehdr
.e_type
!= ET_EXEC
&& ehdr
.e_type
!= ET_REL
)
1342 error (0, 0, "\"%s\" is not a shared library", name
);
1346 /* Allocate DSO structure. Leave place for additional 20 new section
1349 malloc (sizeof(DSO
) + (ehdr
.e_shnum
+ 20) * sizeof(GElf_Shdr
)
1350 + (ehdr
.e_shnum
+ 20) * sizeof(Elf_Scn
*));
1353 error (0, ENOMEM
, "Could not open DSO");
1357 elf_flagelf (elf
, ELF_C_SET
, ELF_F_LAYOUT
);
1359 memset (dso
, 0, sizeof(DSO
));
1362 dso
->scn
= (Elf_Scn
**) &dso
->shdr
[ehdr
.e_shnum
+ 20];
1364 for (i
= 0; i
< ehdr
.e_shnum
; ++i
)
1366 dso
->scn
[i
] = elf_getscn (elf
, i
);
1367 gelf_getshdr (dso
->scn
[i
], dso
->shdr
+ i
);
1370 dso
->filename
= (const char *) strdup (name
);
1376 free ((char *) dso
->filename
);
1386 /* Compute a fresh build ID bit-string from the editted file contents. */
1388 handle_build_id (DSO
*dso
, Elf_Data
*build_id
,
1389 size_t build_id_offset
, size_t build_id_size
)
1391 hashFunctionContext ctx
;
1392 const hashFunction
*hf
= NULL
;
1393 int i
= hashFunctionCount ();
1397 hf
= hashFunctionGet (i
);
1398 if (hf
!= NULL
&& hf
->digestsize
== build_id_size
)
1403 fprintf (stderr
, "Cannot handle %Zu-byte build ID\n", build_id_size
);
1407 if (elf_update (dso
->elf
, ELF_C_NULL
) < 0)
1409 fprintf (stderr
, "Failed to update file: %s\n",
1410 elf_errmsg (elf_errno ()));
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
);
1417 hashFunctionContextInit (&ctx
, hf
);
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. */
1428 auto inline void process (const void *data
, size_t size
);
1429 auto inline void process (const void *data
, size_t size
)
1431 memchunk chunk
= { .data
= (void *) data
, .size
= size
};
1432 hashFunctionContextUpdateMC (&ctx
, &chunk
);
1440 Elf_Data x
= { .d_version
= EV_CURRENT
, .d_buf
= &u
};
1442 x
.d_type
= ELF_T_EHDR
;
1443 x
.d_size
= sizeof u
.ehdr
;
1445 u
.ehdr
.e_phoff
= u
.ehdr
.e_shoff
= 0;
1446 if (elf64_xlatetom (&x
, &x
, dso
->ehdr
.e_ident
[EI_DATA
]) == NULL
)
1449 fprintf (stderr
, "Failed to compute header checksum: %s\n",
1450 elf_errmsg (elf_errno ()));
1454 x
.d_type
= ELF_T_PHDR
;
1455 x
.d_size
= sizeof u
.phdr
;
1456 for (i
= 0; i
< dso
->ehdr
.e_phnum
; ++i
)
1458 if (gelf_getphdr (dso
->elf
, i
, &u
.phdr
) == NULL
)
1460 if (elf64_xlatetom (&x
, &x
, dso
->ehdr
.e_ident
[EI_DATA
]) == NULL
)
1462 process (x
.d_buf
, x
.d_size
);
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
)
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
)
1474 process (x
.d_buf
, x
.d_size
);
1476 if (u
.shdr
.sh_type
!= SHT_NOBITS
)
1478 Elf_Data
*d
= elf_rawdata (dso
->scn
[i
], NULL
);
1481 process (d
->d_buf
, d
->d_size
);
1486 hashFunctionContextDigest (&ctx
, (byte
*) build_id
->d_buf
+ build_id_offset
);
1487 hashFunctionContextFree (&ctx
);
1489 elf_flagdata (build_id
, ELF_C_SET
, ELF_F_DIRTY
);
1491 /* Now format the build ID bits in hex to print out. */
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]);
1497 for (i
= 1; i
< (int)build_id_size
; ++i
)
1499 n
= snprintf (&hex
[i
* 2], 3, "%02" PRIx8
, id
[i
]);
1507 main (int argc
, char *argv
[])
1512 poptContext optCon
; /* context for parsing command-line options */
1515 struct stat stat_buf
;
1517 Elf_Data
*build_id
= NULL
;
1518 size_t build_id_offset
= 0, build_id_size
= 0;
1520 optCon
= poptGetContext("debugedit", argc
, (const char **)argv
, optionsTable
, 0);
1522 while ((nextopt
= poptGetNextOpt (optCon
)) > 0 || nextopt
== POPT_ERROR_BADOPT
)
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
),
1534 args
= poptGetArgs (optCon
);
1535 if (args
== NULL
|| args
[0] == NULL
|| args
[1] != NULL
)
1537 poptPrintHelp(optCon
, stdout
, 0);
1541 if (dest_dir
!= NULL
)
1543 if (base_dir
== NULL
)
1545 fprintf (stderr
, "You must specify a base dir if you specify a dest dir\n");
1548 if (strlen (dest_dir
) > strlen (base_dir
))
1550 fprintf (stderr
, "Only dest dir longer than base dir not supported\n");
1555 /* Make sure there are trailing slashes in dirs */
1556 if (base_dir
!= NULL
&& base_dir
[strlen (base_dir
)-1] != '/')
1558 p
= malloc (strlen (base_dir
) + 2);
1559 strcpy (p
, base_dir
);
1564 if (dest_dir
!= NULL
&& dest_dir
[strlen (dest_dir
)-1] != '/')
1566 p
= malloc (strlen (dest_dir
) + 2);
1567 strcpy (p
, dest_dir
);
1573 if (list_file
!= NULL
)
1575 list_file_fd
= open (list_file
, O_WRONLY
|O_CREAT
|O_APPEND
, 0644);
1580 if (elf_version(EV_CURRENT
) == EV_NONE
)
1582 fprintf (stderr
, "library out of date\n");
1586 if (stat(file
, &stat_buf
) < 0)
1588 fprintf (stderr
, "Failed to open input file '%s': %s\n", file
, strerror(errno
));
1592 /* Make sure we can read and write */
1593 chmod (file
, stat_buf
.st_mode
| S_IRUSR
| S_IWUSR
);
1595 fd
= open (file
, O_RDWR
);
1598 fprintf (stderr
, "Failed to open input file '%s': %s\n", file
, strerror(errno
));
1602 dso
= fdopen_dso (fd
, file
);
1606 for (i
= 1; i
< dso
->ehdr
.e_shnum
; i
++)
1610 switch (dso
->shdr
[i
].sh_type
)
1613 case SHT_MIPS_DWARF
:
1614 name
= strptr (dso
, dso
->ehdr
.e_shstrndx
, dso
->shdr
[i
].sh_name
);
1615 /* TODO: Handle stabs */
1617 if (strcmp (name
, ".stab") == 0)
1618 edit_stabs (dso
, i
);
1620 if (strcmp (name
, ".debug_info") == 0)
1626 && build_id
== NULL
&& (dso
->shdr
[i
].sh_flags
& SHF_ALLOC
))
1628 /* Look for a build-ID note here. */
1629 Elf_Data
*data
= elf_rawdata (elf_getscn (dso
->elf
, i
), NULL
);
1633 .d_version
= EV_CURRENT
, .d_type
= ELF_T_NHDR
,
1634 .d_buf
= &nh
, .d_size
= sizeof nh
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
]))
1643 Elf32_Word len
= sizeof nh
+ nh
.n_namesz
;
1644 len
= (len
+ 3) & ~3;
1646 if (nh
.n_namesz
== sizeof "GNU" && nh
.n_type
== 3
1647 && !memcmp ((char *) src
.d_buf
+ sizeof nh
, "GNU", sizeof "GNU"))
1650 build_id_offset
= (char *) src
.d_buf
+ len
-
1651 (char *) data
->d_buf
;
1652 build_id_size
= nh
.n_descsz
;
1657 len
= (len
+ 3) & ~3;
1658 src
.d_buf
= (char *) src
.d_buf
+ len
;
1667 if (do_build_id
&& build_id
!= NULL
)
1668 handle_build_id (dso
, build_id
, build_id_offset
, build_id_size
);
1670 if (elf_update (dso
->elf
, ELF_C_WRITE
) < 0)
1672 fprintf (stderr
, "Failed to write file: %s\n", elf_errmsg (elf_errno()));
1675 if (elf_end (dso
->elf
) < 0)
1677 fprintf (stderr
, "elf_end failed: %s\n", elf_errmsg (elf_errno()));
1682 /* Restore old access rights */
1683 chmod (file
, stat_buf
.st_mode
);
1685 poptFreeContext (optCon
);