xref: /minix/minix/commands/swifi/extra.c (revision 9f988b79)
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 
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 
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 
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 
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 
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 
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 
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