Introduce 32/64bit macros to use the same code on both platforms
[opensuse:ptools.git] / libproc / proc_service.c
1 /*
2  * proc_service.c - A minimal subset of the proc_service interface.
3  *
4  * Copyright: Jan Blunck
5  */
6
7 #include <stdarg.h>
8 #include <stddef.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11
12 /* The definitions in this file must correspond to those in the debugger.  */
13 #include "proc_service.h"
14 #include "proc_service_impl.h"
15 #include "symbols.h"
16
17 ps_err_e ps_lgetfpregs(struct ps_prochandle *ph, lwpid_t pid,
18                        prfpregset_t *regset)
19 {
20         fprintf(stderr, "%s\n", __FUNCTION__);
21         return PS_ERR;
22 }
23
24 ps_err_e ps_lsetfpregs(struct ps_prochandle *ph, lwpid_t pid,
25                        const prfpregset_t *regset)
26 {
27         fprintf(stderr, "%s\n", __FUNCTION__);
28         return PS_ERR;
29 }
30
31 ps_err_e ps_lgetregs(struct ps_prochandle *ph, lwpid_t pid,
32                      prgregset_t regset)
33 {
34         fprintf(stderr, "%s\n", __FUNCTION__);
35         return ph->ops->lgetregs(ph, pid, regset);
36 }
37
38 ps_err_e ps_lsetregs(struct ps_prochandle *ph, lwpid_t pid,
39                      const prgregset_t regset)
40 {
41         fprintf(stderr, "%s\n", __FUNCTION__);
42         return PS_ERR;
43 }
44
45 pid_t ps_getpid(struct ps_prochandle *ph)
46 {
47         fprintf(stderr, "%s\n", __FUNCTION__);
48         return ph->pid;
49 }
50
51 ps_err_e ps_pglobal_lookup(struct ps_prochandle *ph, const char *object_name,
52                            const char *sym_name, psaddr_t *sym_addr)
53 {
54         const Elf64_Addr *sym;
55
56         sym = findLocalSym(sym_name, ph->symtab);
57
58         fprintf(stderr, "%s(%s,%s) = 0x%x\n", __FUNCTION__, object_name,
59                 sym_name, sym);
60
61         if (!sym)
62                 return PS_NOSYM;
63
64         *sym_addr = (psaddr_t)sym;
65         return PS_OK;
66 }
67
68 ps_err_e ps_pdread(struct ps_prochandle *ph, psaddr_t addr, void *buf,
69                    size_t size)
70 {
71         fprintf(stderr, "%s(addr=0x%x,size=%d)\n", __FUNCTION__, addr, size);
72         return ph->ops->pdread(ph, addr, buf, size);
73 }
74
75 ps_err_e ps_pdwrite(struct ps_prochandle *ph, psaddr_t addr,
76                     const void *buf, size_t size)
77 {
78         fprintf(stderr, "%s\n", __FUNCTION__);
79         return PS_ERR;
80 }
81
82 int ps_init(void)
83 {
84         int err;
85
86         err = ps_symbols_init();
87         if (err)
88                 fprintf(stderr, "proc_service init failed\n");
89
90         return err;
91 }
92
93 void ps_exit(void)
94 {
95         ps_symbols_exit();
96 }
97
98 void ps_abort(const char *msg)
99 {
100         ps_exit();
101         fprintf(stderr, "%s\n", msg);
102         exit(1);
103 }
104
105 void ps_debug(const char* fmt,...)
106 {
107         va_list list;
108
109         va_start(list, fmt);
110         fputs("DEBUG: ", stderr);
111         vfprintf(stderr, fmt, list);
112         va_end(list);
113 }
114
115 void ps_release(struct ps_prochandle *ph)
116 {
117         ph->ops->release(ph);
118 }
119
120 static int read_dynamic_section(struct ps_prochandle *ph)
121 {
122         int err;
123         psaddr_t sym;
124         ElfW(Dyn) dyn;
125         psaddr_t r_debug = 0;
126         psaddr_t r_map_addr;
127         psaddr_t ldbase_addr;
128
129         err = ps_pglobal_lookup(ph, NULL, "_DYNAMIC", &sym);
130         if (err != PS_OK)
131                 return err;
132
133         do {
134                 err = ps_pdread(ph, sym, &dyn, sizeof(ElfW(Dyn)));
135                 if (err != PS_OK)
136                         return err;
137
138                 fprintf(stderr, "dyn: %x 0x%x\n", dyn.d_tag,
139                         dyn.d_un.d_ptr);
140
141                 if (dyn.d_tag == DT_DEBUG) {
142                         r_debug = (psaddr_t) dyn.d_un.d_ptr;
143                         fprintf(stderr,"r_debug at 0x%x\n", r_debug);
144                         break;
145                 }
146
147                 sym += sizeof(ElfW(Dyn));
148         } while(dyn.d_tag != DT_NULL);
149
150         if (r_debug == 0)
151                 return PS_ERR;
152
153         // FIXME: Check the link version and the r_state
154
155         err = ps_pdread(ph, r_debug + offsetof(struct r_debug, r_map),
156                         &r_map_addr, sizeof(psaddr_t));
157         fprintf(stderr,"r_map at 0x%x\n", r_map_addr);
158         err = ps_pdread(ph, r_debug + offsetof(struct r_debug, r_ldbase),
159                         &ldbase_addr, sizeof(psaddr_t));
160         fprintf(stderr,"r_ldbase at 0x%x\n", ldbase_addr);
161
162         return 0;
163 }
164
165 #define PATH_MAX 256
166
167 struct ps_prochandle *ps_attach(pid_t pid)
168 {
169         int res;
170         char filename[PATH_MAX];
171         struct ps_prochandle *ph;
172
173         ph = ptrace_attach(pid);
174         if (!ph)
175                 return NULL;
176
177         snprintf(filename, PATH_MAX, "/proc/%d/exe", pid);
178         if (res < 0) {
179                 ps_release(ph);
180                 return NULL;
181         }
182
183         ph->symtab = loadSyms(filename, 0);
184         if (!ph->symtab) {
185                 fprintf(stderr, "No symbols found.\n");
186                 ps_release(ph);
187                 return NULL;
188         }
189
190         read_dynamic_section(ph);
191         return ph;
192 }