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 asymbol
**new_sympp
, **old_sympp
;
34 int new_symcount
, old_symcount
;
36 int main(int argc
, char **argv
)
39 bfd
*oldbfd
= bfd_openr(argv
[1], NULL
);
40 assert(oldbfd
!= NULL
);
41 newbfd
= bfd_openr(argv
[2], NULL
);
42 assert(newbfd
!= NULL
);
45 assert(bfd_check_format_matches(oldbfd
, bfd_object
, &matching
));
46 assert(bfd_check_format_matches(newbfd
, bfd_object
, &matching
));
48 new_symcount
= get_syms(newbfd
, &new_sympp
);
49 old_symcount
= get_syms(oldbfd
, &old_sympp
);
51 printf("%d\n", bfd_arch_bits_per_address(oldbfd
));
52 foreach_nonmatching(oldbfd
, newbfd
, print_newbfd_section_name
);
54 foreach_nonmatching(oldbfd
, newbfd
, print_newbfd_entry_symbols
);
57 assert(bfd_close(oldbfd
));
58 assert(bfd_close(newbfd
));
62 void foreach_nonmatching(bfd
*oldbfd
, bfd
*newbfd
, section_fn s_fn
)
64 asection
*newp
, *oldp
;
65 for (newp
= newbfd
->sections
; newp
!= NULL
; newp
= newp
->next
) {
66 if (!starts_with(newp
->name
, ".text"))
68 oldp
= bfd_get_section_by_name(oldbfd
, newp
->name
);
70 if (s_fn
== print_newbfd_section_name
)
74 int newsize
= bfd_get_section_size(newp
);
75 int oldsize
= bfd_get_section_size(oldp
);
76 if (newsize
== oldsize
) {
77 void *newmem
= malloc(newsize
);
78 void *oldmem
= malloc(oldsize
);
79 assert(bfd_get_section_contents
80 (oldbfd
, oldp
, oldmem
, 0, oldsize
));
81 assert(bfd_get_section_contents
82 (newbfd
, newp
, newmem
, 0, newsize
));
83 if (memcmp(newmem
, oldmem
, newsize
) == 0 &&
84 reloc_cmp(oldbfd
, oldp
, newbfd
, newp
) == 0)
92 * reloc_cmp checks to see whether the old section and the new section
93 * reference different read-only data in their relocations -- if a hard-coded
94 * string has been changed between the old file and the new file, reloc_cmp
95 * will detect the difference.
97 int reloc_cmp(bfd
*oldbfd
, asection
*oldp
, bfd
*newbfd
, asection
*newp
)
100 struct supersect
*old_ss
, *new_ss
;
102 old_ss
= fetch_supersect(oldbfd
, oldp
, old_sympp
);
103 new_ss
= fetch_supersect(newbfd
, newp
, new_sympp
);
105 if (old_ss
->num_relocs
!= new_ss
->num_relocs
)
108 for (i
= 0; i
< old_ss
->num_relocs
; i
++) {
109 struct supersect
*ro_old_ss
, *ro_new_ss
;
111 asection
*ro_oldp
= (*old_ss
->relocs
[i
]->sym_ptr_ptr
)->section
;
112 asection
*ro_newp
= (*new_ss
->relocs
[i
]->sym_ptr_ptr
)->section
;
114 ro_old_ss
= fetch_supersect(oldbfd
, ro_oldp
, old_sympp
);
115 ro_new_ss
= fetch_supersect(newbfd
, ro_newp
, new_sympp
);
117 if (!starts_with(ro_old_ss
->name
, ".rodata"))
120 if (strcmp(ro_old_ss
->name
, ro_new_ss
->name
) != 0)
124 *(int *)(old_ss
->contents
+ old_ss
->relocs
[i
]->address
);
126 *(int *)(new_ss
->contents
+ new_ss
->relocs
[i
]->address
);
128 if (starts_with(ro_old_ss
->name
, ".rodata.str")) {
130 (ro_old_ss
->contents
+ old_offset
,
131 ro_new_ss
->contents
+ new_offset
) != 0)
136 if (ro_old_ss
->contents_size
!= ro_new_ss
->contents_size
)
139 if (memcmp(ro_old_ss
->contents
,
140 ro_new_ss
->contents
, ro_old_ss
->contents_size
) != 0)
147 void print_newbfd_section_name(asection
*sect
)
149 printf("%s ", sect
->name
);
152 void print_newbfd_entry_symbols(asection
*sect
)
155 for (i
= 0; i
< new_symcount
; i
++) {
156 if (strlen(new_sympp
[i
]->name
) != 0 &&
157 !starts_with(new_sympp
[i
]->name
, ".text") &&
158 strcmp(new_sympp
[i
]->section
->name
, sect
->name
) == 0) {
159 printf("%s ", new_sympp
[i
]->name
);