Change applied flag to a three-state enum.
[ksplice.git] / objdiff.c
blobf34d3a72e1643a87b5e1d0dd8ba8aac1f3195efb
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
14 * 02110-1301, USA.
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"
30 #include "objdiff.h"
32 bfd *newbfd;
33 asymbol **new_sympp, **old_sympp;
34 int new_symcount, old_symcount;
36 int
37 main(int argc, char **argv)
39 bfd_init();
40 bfd *oldbfd = bfd_openr(argv[1], NULL);
41 assert(oldbfd != NULL);
42 newbfd = bfd_openr(argv[2], NULL);
43 assert(newbfd != NULL);
45 char **matching;
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);
54 printf("\n");
55 foreach_nonmatching(oldbfd, newbfd, print_newbfd_entry_symbols);
56 printf("\n");
58 assert(bfd_close(oldbfd));
59 assert(bfd_close(newbfd));
60 printf("ksplice: success\n");
61 return(EXIT_SUCCESS);
64 void
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"))
70 continue;
71 oldp = bfd_get_section_by_name(oldbfd, newp->name);
72 if (oldp == NULL) {
73 if (s_fn == print_newbfd_section_name)
74 s_fn(newp);
75 continue;
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)
88 continue;
90 s_fn(newp);
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)
103 int i;
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)
110 return -1;
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"))
122 continue;
124 if (strcmp(ro_old_ss->name, ro_new_ss->name) != 0)
125 return -1;
127 int old_offset =
128 *(int *) (old_ss->contents + old_ss->relocs[i]->address);
129 int new_offset =
130 *(int *) (new_ss->contents + new_ss->relocs[i]->address);
132 if (starts_with(ro_old_ss->name, ".rodata.str")) {
133 if (strcmp
134 (ro_old_ss->contents + old_offset,
135 ro_new_ss->contents + new_offset) != 0)
136 return -1;
137 continue;
140 if (ro_old_ss->contents_size != ro_new_ss->contents_size)
141 return -1;
143 if (memcmp(ro_old_ss->contents,
144 ro_new_ss->contents, ro_old_ss->contents_size) != 0)
145 return -1;
148 return 0;
151 void
152 print_newbfd_section_name(asection * sect)
154 printf("%s ", sect->name);
157 void
158 print_newbfd_entry_symbols(asection * sect)
160 int i;
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);