1 /*
2 Declaration for Linux kernel compatibility
3 */
4
5 #include <assert.h>
6 #include <stdarg.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <sys/types.h>
10 #include <sys/ptrace.h>
11
12 #include "extra.h"
13
14 pid_t victim_pid= -1;
15 char *victim_exe= NULL;
16
17 #define TRAP_BIT (0x80000000)
18
19 static struct nlist *exe_nlist;
20 static int exe_nlist_n;
21
printk(char * fmt,...)22 void printk(char *fmt, ...)
23 {
24 va_list ap;
25
26 va_start(ap, fmt);
27 vfprintf(stderr, fmt, ap);
28 va_end(ap);
29 }
30
kallsyms_address_to_symbol(db_expr_t off,const char ** mod_name,unsigned long * mod_start,unsigned long * mod_end,const char ** sec_name,unsigned long * sec_start,unsigned long * sec_end,const char ** sym_name,unsigned long * sym_start,unsigned long * sym_end)31 int kallsyms_address_to_symbol(db_expr_t off,
32 const char * *mod_name, unsigned long *mod_start, unsigned long *mod_end,
33 const char * *sec_name, unsigned long *sec_start, unsigned long *sec_end,
34 const char * *sym_name, unsigned long *sym_start, unsigned long *sym_end)
35 {
36 static char name[64];
37
38 int i;
39 unsigned long btext, etext;
40 struct nlist *below, *above;
41
42 off &= ~TRAP_BIT;
43 load_nlist(victim_exe, &btext, &etext);
44 below= above= NULL;
45 for (i= 0; i<exe_nlist_n; i++)
46 {
47 if (exe_nlist[i].n_type != N_TEXT)
48 continue;
49 if (exe_nlist[i].n_value <= off)
50 {
51 if (!below || exe_nlist[i].n_value > below->n_value)
52 below= &exe_nlist[i];
53 }
54 if (exe_nlist[i].n_value > off)
55 {
56 if (!above || exe_nlist[i].n_value < above->n_value)
57 above= &exe_nlist[i];
58 }
59 }
60
61 btext |= TRAP_BIT;
62 etext |= TRAP_BIT;
63
64 *mod_name = victim_exe;
65 *mod_start = btext;
66 *mod_end = etext;
67 *sec_name = ".text";
68 *sec_start = btext;
69 *sec_end = etext;
70
71 assert(below && above);
72
73 strncpy(name, below->n_name, sizeof(name)-1);
74 name[sizeof(name)-1]= '\0';
75 *sym_name= name;
76
77 *sym_start= below->n_value | TRAP_BIT;
78 *sym_end= above->n_value | TRAP_BIT;
79
80 return 1;
81 }
82
text_read_ul(void * addr)83 unsigned long text_read_ul(void *addr)
84 {
85 int i;
86 unsigned long value;
87
88 for (i= 0; i<sizeof(value); i++)
89 {
90 ((unsigned char *)&value)[i]= text_read_ub((char *)addr+i);
91 }
92 return value;
93 }
94
text_read_ub(void * addr)95 unsigned char text_read_ub(void *addr)
96 {
97 int v;
98 unsigned long vaddr;
99
100 vaddr= (unsigned long)addr;
101 vaddr &= ~TRAP_BIT;
102 v= ptrace(T_READB_INS, victim_pid, (void *)vaddr, 0);
103 if (v < 0)
104 {
105 fprintf(stderr,
106 "text_read_ub: trace T_READB_INS failed on pid %d, addr 0x%lx: %s\n",
107 victim_pid, vaddr, strerror(errno));
108 exit(1);
109 }
110 return v;
111 }
112
text_write_ul(void * addr,unsigned long value)113 void text_write_ul(void *addr, unsigned long value)
114 {
115 int i;
116
117 for (i= 0; i<sizeof(value); i++)
118 {
119 text_write_ub((char *)addr+i, ((unsigned char *)&value)[i]);
120 }
121 }
122
text_write_ub(void * addr,unsigned char value)123 void text_write_ub(void *addr, unsigned char value)
124 {
125 int v;
126 unsigned long vaddr;
127
128 vaddr= (unsigned long)addr;
129 vaddr &= ~TRAP_BIT;
130 v= ptrace(T_WRITEB_INS, victim_pid, (void *)vaddr, value);
131 if (v < 0)
132 {
133 fprintf(stderr,
134 "text_read_ub: trace T_WRITEB_INS failed on pid %d, addr 0x%lx: %s\n",
135 victim_pid, vaddr, strerror(errno));
136 exit(1);
137 }
138 }
139
load_nlist(exe_name,btextp,etextp)140 void load_nlist(exe_name, btextp, etextp)
141 char *exe_name;
142 unsigned long *btextp;
143 unsigned long *etextp;
144 {
145 int i;
146 unsigned long btext, etext;
147
148 if (!exe_nlist)
149 {
150 exe_nlist_n= read_nlist(exe_name, &exe_nlist);
151 if (exe_nlist_n <= 0)
152 {
153 if (exe_nlist_n == -1)
154 {
155 fprintf(stderr,
156 "error reading name list from '%s': %s\n",
157 exe_name, strerror(errno));
158 }
159 else
160 fprintf(stderr, "no name list in '%s'\n",
161 exe_name);
162 exit(1);
163 }
164 }
165
166 if (!btextp && !etextp)
167 return;
168
169 etext= 0;
170 btext= (unsigned long)-1;
171 for (i= 0; i<exe_nlist_n; i++)
172 {
173 if (exe_nlist[i].n_type != N_TEXT)
174 continue;
175 if (exe_nlist[i].n_value < btext)
176 btext= exe_nlist[i].n_value;
177 if (exe_nlist[i].n_value > etext)
178 etext= exe_nlist[i].n_value;
179 }
180
181 if (btext >= etext)
182 {
183 fprintf(stderr, "Bad btext (0x%lx) or etext (0x%lx) in %s\n",
184 btext, etext, exe_name);
185 exit(1);
186 }
187
188 btext |= TRAP_BIT;
189 etext |= TRAP_BIT;
190
191 if (btextp)
192 *btextp= btext;
193 if (etextp)
194 *etextp= etext;
195 }
196