Skip to content

Commit 76a0d6b

Browse files
committed
Implement 64-bit loaded, and ARM support
1 parent acd1f56 commit 76a0d6b

File tree

2 files changed

+142
-99
lines changed

2 files changed

+142
-99
lines changed

panda/plugins/loaded/loaded.cpp

Lines changed: 122 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ PANDAENDCOMMENT */
1818
#include <cstdio>
1919
#include <map>
2020
#include <memory>
21+
#include <sys/mman.h>
2122

2223
#include "panda/plugin.h"
2324
#include "panda/plugin_plugin.h"
@@ -52,14 +53,14 @@ PPP_PROT_REG_CB(on_library_load);
5253
// This creates the global for this call back fn (on_library_load)
5354
PPP_CB_BOILERPLATE(on_library_load)
5455

55-
bool debug = true;
56+
bool debug = false;
57+
#define dprintf(...) if (debug) { printf(__VA_ARGS__); fflush(stdout); }
5658

5759
#define MAX_FILENAME 256
5860
std::map <target_ulong, OsiProc> running_procs;
5961

6062
void die(const char* fmt, ...) {
6163
va_list args;
62-
6364
va_start(args, fmt);
6465
vfprintf(stderr, fmt, args);
6566
va_end(args);
@@ -80,116 +81,167 @@ uint32_t guest_strncpy(CPUState *cpu, char *buf, size_t maxlen, target_ulong gue
8081
return i;
8182
}
8283

83-
#if defined(TARGET_I386) && !defined(TARGET_X86_64)
84-
// 125 long sys_mprotect ['unsigned long start', ' size_t len', 'unsigned long prot']
85-
void linux_mprotect_return(CPUState* cpu,target_ulong pc,uint32_t start,uint32_t len,uint32_t prot) {
86-
if (debug) {
87-
printf("[loaded] mprotect()\n");
88-
}
89-
}
90-
// 90 long sys_old_mmap ['struct mmap_arg_struct __user *arg']
91-
void linux_old_mmap_return(CPUState *cpu, target_ulong pc, uint32_t arg_ptr) {
92-
if (debug) {
93-
printf("[loaded] old mmap()\n");
94-
}
95-
}
96-
97-
void linux_mmap_pgoff_return(CPUState *cpu,target_ulong pc,uint32_t addr,uint32_t len,uint32_t prot,uint32_t flags,uint32_t fd,uint32_t pgoff) {
98-
CPUArchState *env = (CPUArchState*)cpu->env_ptr;
99-
target_ulong asid = panda_current_asid(cpu);
100-
if (running_procs.count(asid) == 0) {
101-
//printf ("linux_mmap_pgoff_enter for asid=0x%x fd=%d -- dont know about that asid. discarding \n", (unsigned int) asid, (int) fd);
102-
return;
103-
}
104-
if ((int32_t) fd == -1){
105-
//printf ("linux_mmap_pgoff_enter for asid=0x%x fd=%d flags=%x -- not valid fd . . . \n", (unsigned int) asid, (int) fd, flags);
106-
return;
107-
}
108-
OsiProc proc = running_procs[asid];
109-
char *filename = osi_linux_fd_to_filename(cpu, &proc, fd);
110-
// gets us offset into the file. could be useful
111-
//uint64_t pos = osi_linux_fd_to_pos(env, &proc, fd);
112-
// if a filename exists and permission is executable
113-
// TODO: fix this magic constant of 0x04 for PROT_EXEC
114-
if (filename != NULL && ((prot & 0x04) == 0x04)) {
115-
if (debug) {
116-
printf ("[loaded] linux_mmap_pgoff(fd=%d filename=[%s] "
117-
"len=%d prot=%x flags=%x "
118-
"pgoff=%d)=" TARGET_FMT_lx "\n", (int) fd,
119-
filename, len, prot, flags, pgoff, env->regs[R_EAX]);
120-
}
121-
PPP_RUN_CB(on_library_load, cpu, pc, filename, env->regs[R_EAX], len)
122-
} else if ((prot & 0x04) == 0x04) {
123-
printf("[loaded] mapped executable section without a filename!\n");
124-
printf ("[loaded] linux_mmap_pgoff(fd=%d "
125-
"len=%d prot=%x flags=%x "
126-
"pgoff=%d)=" TARGET_FMT_lx "\n", (int) fd,
127-
len, prot, flags, pgoff, env->regs[R_EAX]);
128-
}
129-
}
130-
#endif
131-
13284
// get current process before each bb execs
13385
// which will probably help us actually know the current process
13486
void osi_foo(CPUState *cpu, TranslationBlock *tb) {
135-
13687
if (panda_in_kernel(cpu)) {
137-
13888
std::unique_ptr<OsiProc, decltype(free_osiproc)*> p { get_current_process(cpu), free_osiproc };
13989

140-
//some sanity checks on what we think the current process is
90+
// some sanity checks on what we think the current process is
14191
// we couldn't find the current task
142-
if (!p) return;
92+
if (!p) {
93+
return;
94+
}
14395
// this means we didnt find current task
144-
if (p->taskd == 0) return;
96+
if (p->taskd == 0) {
97+
return;
98+
}
14599
// or the name
146-
if (p->name == 0) return;
100+
if (p->name == 0) {
101+
return;
102+
}
147103
// this is just not ok
148-
if (((int) p->pid) == -1) return;
104+
if (((int) p->pid) == -1) {
105+
return;
106+
}
149107
uint32_t n = strnlen(p->name, 32);
150108
// name is one char?
151-
if (n<2) return;
109+
if (n < 2) {
110+
return;
111+
}
152112
uint32_t np = 0;
153113
for (uint32_t i=0; i<n; i++) {
154114
np += (isprint(p->name[i]) != 0);
155115
}
156116
// name doesnt consist of solely printable characters
157117
// printf ("np=%d n=%d\n", np, n);
158-
if (np != n) return;
118+
if (np != n) {
119+
return;
120+
}
159121
target_ulong asid = panda_current_asid(cpu);
160122
if (running_procs.count(asid) == 0) {
161-
printf ("adding asid=0x%x to running procs. cmd=[%s] task=0x%x\n", (unsigned int) asid, p->name, (unsigned int) p->taskd);
123+
printf("[loaded] adding asid=0x%x to running procs. cmd=[%s] task=0x%x\n", (unsigned int) asid, p->name, (unsigned int) p->taskd);
162124
}
163125
running_procs[asid] = *p;
164126
}
165-
166127
return;
167128
}
168-
bool init_plugin(void *self) {
169-
//panda_arg_list *args = panda_get_args("loaded");
170129

130+
#if defined(TARGET_I386) || defined(TARGET_ARM)
131+
#if defined(TARGET_I386) && !defined(TARGET_X86_64) || defined(TARGET_ARM) && !defined(TARGET_AARCH64)
132+
// technically for 32-bit it is pgoff, not offset! But I want to avoid code duplication!
133+
void linux_mmap_return(CPUState *cpu, target_ulong pc, uint32_t addr, uint32_t len, uint32_t prot, uint32_t flags, uint32_t fd, uint32_t offset)
134+
#elif defined(TARGET_X86_64)
135+
void linux_mmap_return(CPUState *cpu, target_ulong pc, uint64_t addr, uint64_t len, uint64_t prot, uint64_t flags, uint64_t fd, uint64_t offset)
136+
#elif defined(TARGET_AARCH64)
137+
void linux_mmap_return(CPUState* cpu, target_ulong pc, uint64_t addr, uint32_t len, int32_t prot, int32_t flags, int32_t fd, uint64_t offset)
138+
#endif
139+
{
140+
dprintf("[loaded] linux_mmap_return is called!\n");
141+
CPUArchState *env = (CPUArchState*)cpu->env_ptr;
142+
target_ulong asid = panda_current_asid(cpu);
143+
if (running_procs.count(asid) == 0) {
144+
return;
145+
}
146+
if (fd == -1) {
147+
return;
148+
}
149+
dprintf("[loaded] linux_mmap_return is called, with OK fd and non-zero running proc\n");
150+
OsiProc proc = running_procs[asid];
151+
char *filename = osi_linux_fd_to_filename(cpu, &proc, fd);
152+
// gets us offset into the file. could be useful
153+
// uint64_t pos = osi_linux_fd_to_pos(env, &proc, fd);
154+
// if a filename exists and permission is executable
155+
#if defined(TARGET_I386) && !defined(TARGET_X86_64)
156+
dprintf("[loaded] linux_mmap_pgoff(fd=%d filename=[%s] "
157+
"len=%d prot=%x flags=%x "
158+
"pgoffset=%d)=" TARGET_FMT_lx "\n", (int) fd,
159+
filename, len, prot, flags, offset, env->regs[R_EAX]);
160+
#elif defined(TARGET_ARM) && !defined(TARGET_AARCH64)
161+
dprintf("[loaded] linux_mmap_pgoff(fd=%d filename=[%s] "
162+
"len=%u prot=%u flags=%u "
163+
"pgoffset=%d)=" TARGET_FMT_lx "\n", (int) fd,
164+
filename, len, prot, flags, offset, env->regs[0]);
165+
#elif defined(TARGET_X86_64)
166+
dprintf("[loaded] linux_mmap_pgoff(fd=%lu filename=[%s] "
167+
"len=%lu prot=%lu flags=%lu "
168+
"pgoff=%lu)=" TARGET_FMT_lx "\n", (unsigned long) fd,
169+
filename, (unsigned long) len, (unsigned long) prot, (unsigned long) flags, (unsigned long) offset, env->regs[R_EAX]);
170+
#elif defined(TARGET_AARCH64)
171+
printf("[loaded] linux_mmap(fd=%d filename=[%s] "
172+
"len=%u prot=%x flags=%x "
173+
"pgoff=%lu)=" TARGET_FMT_lx "\n", fd,
174+
filename, len, prot, flags, offset, env->xregs[0]);
175+
#endif
176+
177+
if (filename != NULL && ((prot & PROT_EXEC) == PROT_EXEC)) {
178+
// See 'dwarf2.cpp' for the definition of 'on_library_load'
179+
dprintf("[loaded] Calling on_library_load\n");
180+
#if defined(TARGET_I386)
181+
PPP_RUN_CB(on_library_load, cpu, pc, filename, env->regs[R_EAX], len);
182+
#elif defined(TARGET_AARCH64)
183+
PPP_RUN_CB(on_library_load, cpu, pc, filename, env->xregs[0], len);
184+
#elif defined(TARGET_ARM) && !defined(TARGET_AARCH64)
185+
PPP_RUN_CB(on_library_load, cpu, pc, filename, env->regs[0], len);
186+
#endif
187+
}
188+
else if ((prot & PROT_EXEC) == PROT_EXEC) {
189+
printf("[loaded] mapped executable section without a filename!\n");
190+
}
191+
else {
192+
if (filename == NULL) {
193+
dprintf("[loaded] I got a null file name\n");
194+
}
195+
else {
196+
dprintf("[loaded] It seems like filename %s was null, OR PROT_EXEC was not there\n", filename);
197+
}
198+
}
199+
}
200+
#endif
201+
202+
bool init_plugin(void *self) {
171203
panda_require("osi");
172204
assert(init_osi_api());
173205
panda_require("osi_linux");
174206
assert(init_osi_linux_api());
175207
panda_require("syscalls2");
208+
panda_arg_list *args = panda_get_args("loaded");
209+
debug = panda_parse_bool_opt(args, "debug", "enable debug output");
176210

177211
#if defined(TARGET_I386) && !defined(TARGET_X86_64)
178212
{
179213
panda_cb pcb;
180214
pcb.before_block_exec = osi_foo;
181215
panda_register_callback(self, PANDA_CB_BEFORE_BLOCK_EXEC, pcb);
182216
}
217+
PPP_REG_CB("syscalls2", on_sys_mmap_pgoff_return, linux_mmap_return);
218+
printf("[loaded] The plugin is supported on i386\n");
219+
#elif defined(TARGET_ARM) && !defined(TARGET_AARCH64)
220+
{
221+
panda_cb pcb;
222+
pcb.before_block_exec = osi_foo;
223+
panda_register_callback(self, PANDA_CB_BEFORE_BLOCK_EXEC, pcb);
224+
}
183225

184-
PPP_REG_CB("syscalls2", on_sys_mmap_pgoff_return, linux_mmap_pgoff_return);
185-
// don't use these at them moment
186-
//PPP_REG_CB("syscalls2", on_sys_old_mmap_return, linux_old_mmap_return);
187-
//PPP_REG_CB("syscalls2", on_sys_mprotect_return, linux_mprotect_return);
226+
PPP_REG_CB("syscalls2", on_do_mmap2_return, linux_mmap_return);
227+
printf("[loaded] The plugin is supported on ARM 32-bits\n");
228+
#elif defined(TARGET_X86_64) || defined(TARGET_AARCH64)
229+
{
230+
panda_cb pcb;
231+
pcb.before_block_exec = osi_foo;
232+
panda_register_callback(self, PANDA_CB_BEFORE_BLOCK_EXEC, pcb);
233+
}
234+
// Tell Plugin 'syscall2', that if a systemcall 'mmap' occurs, then run the code in 'linux_mmap_return'
235+
// https://www.linuxquestions.org/questions/linux-general-1/difference-between-mmap2-syscall-and-mmap_pgoff-syscall-for-32-bit-linux-4175622986/
236+
PPP_REG_CB("syscalls2", on_sys_mmap_return, linux_mmap_return);
237+
printf("[loaded] The plugin is supported on x86-64 and ARM 64-bits\n");
188238
#else
189-
fprintf(stderr, "The loaded plugin is not currently supported on this platform.\n");
239+
fprintf(stderr, "[loaded] The plugin is not currently supported on this platform.\n");
190240
return false;
191241
#endif
192242
return true;
193243
}
194244

195-
void uninit_plugin(void *self) { }
245+
void uninit_plugin(void *self) {
246+
printf("[loaded] uninit_plugin\n");
247+
}

panda/plugins/loaded_libs/loaded_libs.cpp

Lines changed: 20 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,20 @@
11
#define __STDC_FORMAT_MACROS
22

33
#include <cstdio>
4-
54
#include "panda/plugin.h"
65

76
#include "syscalls2/syscalls_ext_typedefs.h"
87
#include "syscalls2/syscalls2_info.h"
98
#include "syscalls2/syscalls2_ext.h"
109

1110
extern "C" {
12-
13-
bool init_plugin(void *);
14-
void uninit_plugin(void *);
11+
bool init_plugin(void *);
12+
void uninit_plugin(void *);
1513

1614
#include "osi/osi_types.h"
1715
#include "osi/osi_ext.h"
1816
}
1917

20-
2118
#include<map>
2219
#include<vector>
2320
#include<set>
@@ -40,24 +37,31 @@ uint64_t get_libs_failed_count = 0;
4037
void get_libs(CPUState *env) {
4138

4239
get_libs_count ++;
43-
4440
bool fail = false;
4541
OsiProc *current = get_current_process(env);
46-
if (current == NULL) fail=true;
47-
if (program_name && strcmp(current->name, program_name)) fail=true;
48-
if (current->pid == 0) fail=true;
42+
if (current == NULL) {
43+
fail = true;
44+
}
45+
if (program_name && strcmp(current->name, program_name)) {
46+
fail = true;
47+
}
48+
if (current->pid == 0) {
49+
fail = true;
50+
}
4951
GArray *ms = get_mappings(env, current);
50-
if (ms == NULL) fail=true;
52+
if (ms == NULL) {
53+
fail = true;
54+
}
5155
OsiThread *thread = get_current_thread(env);
52-
if (thread == NULL) fail=true;
53-
56+
if (thread == NULL) {
57+
fail = true;
58+
}
5459
assert (pandalog);
5560

5661
if (fail) {
5762
get_libs_failed_count ++;
5863
}
5964
else {
60-
6165
Panda__LogEntry ple = PANDA__LOG_ENTRY__INIT;
6266
Panda__LoadedLibs ll = PANDA__LOADED_LIBS__INIT;
6367
Panda__Module** m = (Panda__Module **) malloc (sizeof (Panda__Module *) * ms->len);
@@ -90,7 +94,6 @@ void get_libs(CPUState *env) {
9094
ll.tid = thread->tid;
9195

9296
Asid asid = panda_current_asid(env);
93-
9497
ple.has_asid = true;
9598
ple.asid = asid;
9699
ple.asid_libraries = &ll;
@@ -102,41 +105,32 @@ void get_libs(CPUState *env) {
102105
}
103106
free(m);
104107
}
105-
106108
cleanup_osi(current, thread, ms);
107109
}
108110

109-
110-
111111
// 9 long sys_mmap(
112-
113112
void mmap_return(CPUState *cpu, target_ulong pc, unsigned long addr, unsigned long length, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long offset) {
114113
get_libs(cpu);
115114
}
116115

117-
118116
uint64_t bb_count = 0;
119-
120117
void before_block(CPUState *env, TranslationBlock *tb) {
121-
122118
// check up on module list every 50 bb
123119
bb_count ++;
124120
if ((bb_count % 100) == 0) {
125121
get_libs(env);
126122
}
127-
128123
}
129124

130-
131125
bool init_plugin(void *self) {
132126
panda_require("osi");
133127
assert(init_osi_api());
134128
panda_require("syscalls2");
135129

136-
#ifdef TARGET_X86_64
137-
PPP_REG_CB("syscalls2", on_sys_mmap_return, mmap_return);
130+
#if defined(TARGET_X86_64)
131+
PPP_REG_CB("syscalls2", on_sys_mmap_return, mmap_return);
138132
#else
139-
/* #error "No on_sys_mmap_return for target" */
133+
printf("[loaded_libs] mmap_return not supported on this architecture\n");
140134
#endif
141135

142136
panda_cb pcb;
@@ -146,14 +140,11 @@ bool init_plugin(void *self) {
146140
panda_arg_list *args;
147141
args = panda_get_args("loaded_libs");
148142
program_name = panda_parse_string_opt(args, "program_name", NULL, "program name to collect libraries for");
149-
150143
return true;
151144
}
152145

153146
void uninit_plugin(void *self) {
154-
155147
cout << "get_libs_count = " << get_libs_count << "\n";
156148
cout << "get_libs_failed_count = " << get_libs_failed_count << "\n";
157149
cout << "frac = " << ((float) get_libs_failed_count) / get_libs_count << "\n";
158-
159150
}

0 commit comments

Comments
 (0)