Add explanation of map_printk check.
[ksplice.git] / objdiff.c
blob46829712287d70eb2e11bb8ba8694dce315e9d5f
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 main(int argc, char **argv)
38 bfd_init();
39 bfd *oldbfd = bfd_openr(argv[1], NULL);
40 assert(oldbfd != NULL);
41 newbfd = bfd_openr(argv[2], NULL);
42 assert(newbfd != NULL);
44 char **matching;
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);
53 printf("\n");
54 foreach_nonmatching(oldbfd, newbfd, print_newbfd_entry_symbols);
55 printf("\n");
57 assert(bfd_close(oldbfd));
58 assert(bfd_close(newbfd));
59 return EXIT_SUCCESS;
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"))
67 continue;
68 oldp = bfd_get_section_by_name(oldbfd, newp->name);
69 if (oldp == NULL) {
70 if (s_fn == print_newbfd_section_name)
71 s_fn(newp);
72 continue;
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)
85 continue;
87 s_fn(newp);
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)
99 int i;
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)
106 return -1;
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"))
118 continue;
120 if (strcmp(ro_old_ss->name, ro_new_ss->name) != 0)
121 return -1;
123 int old_offset =
124 *(int *)(old_ss->contents + old_ss->relocs[i]->address);
125 int new_offset =
126 *(int *)(new_ss->contents + new_ss->relocs[i]->address);
128 if (starts_with(ro_old_ss->name, ".rodata.str")) {
129 if (strcmp
130 (ro_old_ss->contents + old_offset,
131 ro_new_ss->contents + new_offset) != 0)
132 return -1;
133 continue;
136 if (ro_old_ss->contents_size != ro_new_ss->contents_size)
137 return -1;
139 if (memcmp(ro_old_ss->contents,
140 ro_new_ss->contents, ro_old_ss->contents_size) != 0)
141 return -1;
144 return 0;
147 void print_newbfd_section_name(asection *sect)
149 printf("%s ", sect->name);
152 void print_newbfd_entry_symbols(asection *sect)
154 int i;
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);