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
;
37 main(int argc
, char **argv
)
40 bfd
*oldbfd
= bfd_openr(argv
[1], NULL
);
41 assert(oldbfd
!= NULL
);
42 newbfd
= bfd_openr(argv
[2], NULL
);
43 assert(newbfd
!= NULL
);
46 assert(bfd_check_format_matches(oldbfd
, bfd_object
, &matching
));
47 assert(bfd_check_format_matches(newbfd
, bfd_object
, &matching
));
49 new_symcount
= get_syms(newbfd
, &new_sympp
);
50 old_symcount
= get_syms(oldbfd
, &old_sympp
);
52 printf("%d\n", bfd_arch_bits_per_address(oldbfd
));
53 foreach_nonmatching(oldbfd
, newbfd
, print_newbfd_section_name
);
55 foreach_nonmatching(oldbfd
, newbfd
, print_newbfd_entry_symbols
);
58 assert(bfd_close(oldbfd
));
59 assert(bfd_close(newbfd
));
60 printf("ksplice: success\n");
65 foreach_nonmatching(bfd
* oldbfd
, bfd
* newbfd
, section_fn s_fn
)
67 asection
*newp
, *oldp
;
68 for (newp
= newbfd
->sections
; newp
!= NULL
; newp
= newp
->next
) {
69 if (!starts_with(newp
->name
, ".text"))
71 oldp
= bfd_get_section_by_name(oldbfd
, newp
->name
);
73 if (s_fn
== print_newbfd_section_name
)
77 int newsize
= bfd_get_section_size(newp
);
78 int oldsize
= bfd_get_section_size(oldp
);
79 if (newsize
== oldsize
) {
80 void *newmem
= malloc(newsize
);
81 void *oldmem
= malloc(oldsize
);
82 assert(bfd_get_section_contents
83 (oldbfd
, oldp
, oldmem
, 0, oldsize
));
84 assert(bfd_get_section_contents
85 (newbfd
, newp
, newmem
, 0, newsize
));
86 if (memcmp(newmem
, oldmem
, newsize
) == 0 &&
87 reloc_cmp(oldbfd
, oldp
, newbfd
, newp
) == 0)
95 * reloc_cmp checks to see whether the old section and the new section
96 * reference different read-only data in their relocations -- if a hard-coded
97 * string has been changed between the old file and the new file, reloc_cmp
98 * will detect the difference.
101 reloc_cmp(bfd
* oldbfd
, asection
* oldp
, bfd
* newbfd
, asection
* newp
)
104 struct supersect
*old_ss
, *new_ss
;
106 old_ss
= fetch_supersect(oldbfd
, oldp
, old_sympp
);
107 new_ss
= fetch_supersect(newbfd
, newp
, new_sympp
);
109 if (old_ss
->num_relocs
!= new_ss
->num_relocs
)
112 for (i
= 0; i
< old_ss
->num_relocs
; i
++) {
113 struct supersect
*ro_old_ss
, *ro_new_ss
;
115 asection
*ro_oldp
= (*old_ss
->relocs
[i
]->sym_ptr_ptr
)->section
;
116 asection
*ro_newp
= (*new_ss
->relocs
[i
]->sym_ptr_ptr
)->section
;
118 ro_old_ss
= fetch_supersect(oldbfd
, ro_oldp
, old_sympp
);
119 ro_new_ss
= fetch_supersect(newbfd
, ro_newp
, new_sympp
);
121 if (!starts_with(ro_old_ss
->name
, ".rodata"))
124 if (strcmp(ro_old_ss
->name
, ro_new_ss
->name
) != 0)
128 *(int *) (old_ss
->contents
+ old_ss
->relocs
[i
]->address
);
130 *(int *) (new_ss
->contents
+ new_ss
->relocs
[i
]->address
);
132 if (starts_with(ro_old_ss
->name
, ".rodata.str")) {
134 (ro_old_ss
->contents
+ old_offset
,
135 ro_new_ss
->contents
+ new_offset
) != 0)
140 if (ro_old_ss
->contents_size
!= ro_new_ss
->contents_size
)
143 if (memcmp(ro_old_ss
->contents
,
144 ro_new_ss
->contents
, ro_old_ss
->contents_size
) != 0)
152 print_newbfd_section_name(asection
* sect
)
154 printf("%s ", sect
->name
);
158 print_newbfd_entry_symbols(asection
* sect
)
161 for (i
= 0; i
< new_symcount
; i
++) {
162 if (strlen(new_sympp
[i
]->name
) != 0 &&
163 !starts_with(new_sympp
[i
]->name
, ".text") &&
164 strcmp(new_sympp
[i
]->section
->name
, sect
->name
) == 0) {
165 printf("%s ", new_sympp
[i
]->name
);