1 /* Copyright (C) 2008 Jeffrey Brian Arnold <jbarnold@mit.edu>
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License, version 2.
6 * This program is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 * GNU General Public License for more details.
11 * You should have received a copy of the GNU General Public License
12 * along with this program; if not, write to the Free Software
13 * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
18 * "objdiff old.o new.o" prints two lists to STDOUT, one per line:
19 * (1) the names of the ELF sections in new.o that either
20 * (a) do not appear in old.o, or
21 * (b) have different contents in old.o and new.o
22 * (2) the names of the "entry point" ELF symbols in new.o
23 * corresponding to the ELF sections in list (1)
25 * Before printing these two lists, objdiff prints the number of bits
26 * per address on the target architecture.
29 #include "objcommon.h"
33 struct asymbolp_vec new_syms
, old_syms
;
35 int main(int argc
, char **argv
)
38 bfd
*oldbfd
= bfd_openr(argv
[1], NULL
);
39 assert(oldbfd
!= NULL
);
40 newbfd
= bfd_openr(argv
[2], NULL
);
41 assert(newbfd
!= NULL
);
44 assert(bfd_check_format_matches(oldbfd
, bfd_object
, &matching
));
45 assert(bfd_check_format_matches(newbfd
, bfd_object
, &matching
));
47 get_syms(newbfd
, &new_syms
);
48 get_syms(oldbfd
, &old_syms
);
50 printf("%d\n", bfd_arch_bits_per_address(oldbfd
));
51 foreach_nonmatching(oldbfd
, newbfd
, print_newbfd_section_name
);
53 foreach_nonmatching(oldbfd
, newbfd
, print_newbfd_entry_symbols
);
56 assert(bfd_close(oldbfd
));
57 assert(bfd_close(newbfd
));
61 void foreach_nonmatching(bfd
*oldbfd
, bfd
*newbfd
, section_fn s_fn
)
63 asection
*newp
, *oldp
;
64 for (newp
= newbfd
->sections
; newp
!= NULL
; newp
= newp
->next
) {
65 if (!starts_with(newp
->name
, ".text"))
67 oldp
= bfd_get_section_by_name(oldbfd
, newp
->name
);
69 if (s_fn
== print_newbfd_section_name
)
73 int newsize
= bfd_get_section_size(newp
);
74 int oldsize
= bfd_get_section_size(oldp
);
75 if (newsize
== oldsize
) {
76 void *newmem
= malloc(newsize
);
77 void *oldmem
= malloc(oldsize
);
78 assert(bfd_get_section_contents
79 (oldbfd
, oldp
, oldmem
, 0, oldsize
));
80 assert(bfd_get_section_contents
81 (newbfd
, newp
, newmem
, 0, newsize
));
82 if (memcmp(newmem
, oldmem
, newsize
) == 0 &&
83 reloc_cmp(oldbfd
, oldp
, newbfd
, newp
) == 0)
91 * reloc_cmp checks to see whether the old section and the new section
92 * reference different read-only data in their relocations -- if a hard-coded
93 * string has been changed between the old file and the new file, reloc_cmp
94 * will detect the difference.
96 int reloc_cmp(bfd
*oldbfd
, asection
*oldp
, bfd
*newbfd
, asection
*newp
)
99 struct supersect
*old_ss
, *new_ss
;
101 old_ss
= fetch_supersect(oldbfd
, oldp
, &old_syms
);
102 new_ss
= fetch_supersect(newbfd
, newp
, &new_syms
);
104 if (old_ss
->relocs
.size
!= new_ss
->relocs
.size
)
107 for (i
= 0; i
< old_ss
->relocs
.size
; i
++) {
108 struct supersect
*ro_old_ss
, *ro_new_ss
;
111 (*old_ss
->relocs
.data
[i
]->sym_ptr_ptr
)->section
;
113 (*new_ss
->relocs
.data
[i
]->sym_ptr_ptr
)->section
;
115 ro_old_ss
= fetch_supersect(oldbfd
, ro_oldp
, &old_syms
);
116 ro_new_ss
= fetch_supersect(newbfd
, ro_newp
, &new_syms
);
118 if (!starts_with(ro_old_ss
->name
, ".rodata"))
121 if (strcmp(ro_old_ss
->name
, ro_new_ss
->name
) != 0)
124 int old_offset
= *(int *)(old_ss
->contents
.data
+
125 old_ss
->relocs
.data
[i
]->address
);
126 int new_offset
= *(int *)(new_ss
->contents
.data
+
127 new_ss
->relocs
.data
[i
]->address
);
129 if (starts_with(ro_old_ss
->name
, ".rodata.str")) {
131 (ro_old_ss
->contents
.data
+ old_offset
,
132 ro_new_ss
->contents
.data
+ new_offset
) != 0)
137 if (ro_old_ss
->contents
.size
!= ro_new_ss
->contents
.size
)
140 if (memcmp(ro_old_ss
->contents
.data
, ro_new_ss
->contents
.data
,
141 ro_old_ss
->contents
.size
) != 0)
148 void print_newbfd_section_name(asection
*sect
)
150 printf("%s ", sect
->name
);
153 void print_newbfd_entry_symbols(asection
*sect
)
156 for (symp
= new_syms
.data
; symp
< new_syms
.data
+ new_syms
.size
;
158 asymbol
*sym
= *symp
;
159 if (strlen(sym
->name
) != 0 &&
160 !starts_with(sym
->name
, ".text") &&
161 strcmp(sym
->section
->name
, sect
->name
) == 0)
162 printf("%s ", sym
->name
);