more features
This commit is contained in:
parent
2189e55cde
commit
e8a7b96999
5 changed files with 676 additions and 0 deletions
187
src/libmach/cmdline.c
Normal file
187
src/libmach/cmdline.c
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <mach.h>
|
||||
|
||||
Fhdr *symhdr;
|
||||
Fhdr *corhdr;
|
||||
char *symfil;
|
||||
char *corfil;
|
||||
int corpid;
|
||||
Regs *correg;
|
||||
Map *symmap;
|
||||
Map *cormap;
|
||||
|
||||
int
|
||||
alldigs(char *s)
|
||||
{
|
||||
while(*s){
|
||||
if(*s<'0' || '9'<*s)
|
||||
return 0;
|
||||
s++;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* attach to arguments in argc, argv
|
||||
*/
|
||||
int
|
||||
attachargs(int argc, char **argv, int omode)
|
||||
{
|
||||
int i;
|
||||
Fhdr *hdr;
|
||||
char *s;
|
||||
|
||||
symhdr = nil;
|
||||
corhdr = nil;
|
||||
symfil = nil;
|
||||
corfil = nil;
|
||||
corpid = 0;
|
||||
correg = nil;
|
||||
|
||||
for(i=0; i<argc; i++){
|
||||
if(alldigs(argv[i])){
|
||||
if(corpid){
|
||||
fprint(2, "already have corpid %d; ignoring corpid %d\n", corpid, argv[i]);
|
||||
continue;
|
||||
}
|
||||
if(corhdr){
|
||||
fprint(2, "already have core %s; ignoring corpid %d\n", corfil, corpid);
|
||||
continue;
|
||||
}
|
||||
corpid = atoi(argv[i]);
|
||||
continue;
|
||||
}
|
||||
if((hdr = crackhdr(argv[i], omode)) == nil){
|
||||
fprint(2, "crackhdr %s: %r\n", argv[i]);
|
||||
continue;
|
||||
}
|
||||
fprint(2, "%s: %s %s %s\n", argv[i], hdr->aname, hdr->mname, hdr->fname);
|
||||
if(hdr->ftype == FCORE){
|
||||
if(corpid){
|
||||
fprint(2, "already have corpid %d; ignoring core %s\n", corpid, argv[i]);
|
||||
uncrackhdr(hdr);
|
||||
continue;
|
||||
}
|
||||
if(corhdr){
|
||||
fprint(2, "already have core %s; ignoring core %s\n", corfil, argv[i]);
|
||||
uncrackhdr(hdr);
|
||||
continue;
|
||||
}
|
||||
corhdr = hdr;
|
||||
corfil = argv[i];
|
||||
}else{
|
||||
if(symhdr){
|
||||
fprint(2, "already have text %s; ignoring text %s\n", symfil, argv[i]);
|
||||
uncrackhdr(hdr);
|
||||
continue;
|
||||
}
|
||||
symhdr = hdr;
|
||||
symfil = argv[i];
|
||||
}
|
||||
}
|
||||
|
||||
if(symhdr == nil){
|
||||
symfil = "a.out"; /* default */
|
||||
if(corpid){ /* try from corpid */
|
||||
if((s = proctextfile(corpid)) != nil){
|
||||
fprint(2, "corpid %d: text %s\n", corpid, s);
|
||||
symfil = s;
|
||||
}
|
||||
}
|
||||
if(corhdr){ /* try from core */
|
||||
if(corhdr->txtfil != nil){
|
||||
fprint(2, "core %s: text %s\n", corfil, corhdr->txtfil);
|
||||
symfil = corhdr->txtfil;
|
||||
}
|
||||
}
|
||||
if((symhdr = crackhdr(symfil, omode)) == nil){
|
||||
fprint(2, "crackhdr %s: %r\n", symfil);
|
||||
symfil = nil;
|
||||
}
|
||||
}
|
||||
|
||||
if(symhdr)
|
||||
syminit(symhdr);
|
||||
|
||||
if(!mach)
|
||||
mach = machcpu;
|
||||
|
||||
/*
|
||||
* Set up maps
|
||||
*/
|
||||
symmap = allocmap();
|
||||
cormap = allocmap();
|
||||
if(symmap == nil || cormap == nil)
|
||||
sysfatal("allocating maps: %r");
|
||||
|
||||
if(symhdr){
|
||||
if(mapfile(symhdr, 0, symmap, nil) < 0)
|
||||
fprint(2, "mapfile %s: %r\n", symfil);
|
||||
mapfile(symhdr, 0, cormap, nil);
|
||||
}
|
||||
|
||||
if(corpid)
|
||||
attachproc(corpid);
|
||||
|
||||
if(corhdr)
|
||||
attachcore(corhdr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int thecorpid;
|
||||
static Fhdr *thecorhdr;
|
||||
|
||||
static void
|
||||
unattach(void)
|
||||
{
|
||||
unmapproc(cormap);
|
||||
unmapfile(corhdr, cormap);
|
||||
free(correg);
|
||||
correg = nil;
|
||||
thecorpid = 0;
|
||||
thecorhdr = nil;
|
||||
corpid = 0;
|
||||
corhdr = nil;
|
||||
corfil = nil;
|
||||
}
|
||||
|
||||
int
|
||||
attachproc(int pid)
|
||||
{
|
||||
unattach();
|
||||
if(pid == 0)
|
||||
return 0;
|
||||
if(mapproc(pid, cormap, &correg) < 0){
|
||||
fprint(2, "attachproc %d: %r\n", pid);
|
||||
return -1;
|
||||
}
|
||||
thecorpid = pid;
|
||||
corpid = pid;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
attachcore(Fhdr *hdr)
|
||||
{
|
||||
unattach();
|
||||
if(corhdr == nil)
|
||||
return 0;
|
||||
if(mapfile(hdr, 0, cormap, &correg) < 0){
|
||||
fprint(2, "attachcore %s: %r\n", hdr->filename);
|
||||
return -1;
|
||||
}
|
||||
thecorhdr = hdr;
|
||||
corhdr = hdr;
|
||||
corfil = hdr->filename;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
attachdynamic(void)
|
||||
{
|
||||
elfdl386mapdl();
|
||||
return 0;
|
||||
}
|
||||
|
||||
133
src/libmach/elfdl386.c
Normal file
133
src/libmach/elfdl386.c
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <mach.h>
|
||||
#include "elf.h"
|
||||
|
||||
/*
|
||||
aggr Linkdebug
|
||||
{
|
||||
'X' 0 version;
|
||||
'X' 4 map;
|
||||
};
|
||||
|
||||
aggr Linkmap
|
||||
{
|
||||
'X' 0 addr;
|
||||
'X' 4 name;
|
||||
'X' 8 dynsect;
|
||||
'X' 12 next;
|
||||
'X' 16 prev;
|
||||
};
|
||||
*/
|
||||
enum
|
||||
{
|
||||
DT_NULL = 0,
|
||||
DT_NEEDED,
|
||||
DT_PLTRRELSZ,
|
||||
DT_PLTGOT,
|
||||
DT_HASH,
|
||||
DT_STRTAB,
|
||||
DT_SYMTAB,
|
||||
DT_RELA,
|
||||
DT_RELASZ = 8,
|
||||
DT_RELAENT,
|
||||
DT_STSZ,
|
||||
DT_SYMENT,
|
||||
DT_INIT,
|
||||
DT_FINI,
|
||||
DT_SONAME,
|
||||
DT_RPATH,
|
||||
DT_SYMBOLIC = 16,
|
||||
DT_REL,
|
||||
DT_RELSZ,
|
||||
DT_RELENT,
|
||||
DT_PLTREL,
|
||||
DT_DEBUG,
|
||||
DT_TEXTREL,
|
||||
DT_JMPREL,
|
||||
};
|
||||
|
||||
static int
|
||||
getstr(Map *map, ulong addr, char *buf, uint nbuf)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; i<nbuf; i++){
|
||||
if(get1(map, addr+i, buf+i, 1) < 0)
|
||||
return -1;
|
||||
if(buf[i] == 0)
|
||||
return 0;
|
||||
}
|
||||
return -1; /* no nul */
|
||||
}
|
||||
|
||||
static ulong
|
||||
dyninfo(Fhdr *hdr, int x)
|
||||
{
|
||||
u32int addr, u;
|
||||
|
||||
if(hdr == nil || (addr = ((Elf*)hdr->elf)->dynamic) == 0){
|
||||
fprint(2, "no hdr/dynamic %p\n", hdr);
|
||||
return 0;
|
||||
}
|
||||
addr += hdr->base;
|
||||
|
||||
while(addr != 0){
|
||||
if(get4(cormap, addr, &u) < 0)
|
||||
return 0;
|
||||
if(u == x){
|
||||
if(get4(cormap, addr+4, &u) < 0)
|
||||
return 0;
|
||||
return u;
|
||||
}
|
||||
addr += 8;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
elfdl386mapdl(void)
|
||||
{
|
||||
int i;
|
||||
Fhdr *hdr;
|
||||
u32int linkdebug, linkmap, name, addr;
|
||||
char buf[1024];
|
||||
|
||||
print("elfdl386mapdl\n");
|
||||
if((linkdebug = dyninfo(symhdr, DT_DEBUG)) == 0){
|
||||
fprint(2, "no dt_debug section\n");
|
||||
return;
|
||||
}
|
||||
if(get4(cormap, linkdebug+4, &linkmap) < 0){
|
||||
fprint(2, "get4 linkdebug+4 (0x%lux) failed\n", linkdebug);
|
||||
return;
|
||||
}
|
||||
|
||||
for(i=0; i<100 && linkmap != 0; i++){
|
||||
if(get4(cormap, linkmap, &addr) < 0
|
||||
|| get4(cormap, linkmap+4, &name) < 0
|
||||
|| get4(cormap, linkmap+12, &linkmap) < 0)
|
||||
break;
|
||||
|
||||
if(name
|
||||
&& getstr(cormap, name, buf, sizeof buf) >= 0
|
||||
&& buf[0]
|
||||
&& access(buf, AEXIST) >= 0){
|
||||
if((hdr = crackhdr(buf, OREAD)) == nil)
|
||||
fprint(2, "crackhdr %s: %r\n", buf);
|
||||
else{
|
||||
fprint(2, "%s: %s %s %s\n", buf, hdr->aname, hdr->mname, hdr->fname);
|
||||
hdr->base = addr;
|
||||
if(mapfile(hdr, addr, symmap, nil) < 0)
|
||||
fprint(2, "mapfile %s: %r\n", buf);
|
||||
if(corhdr){
|
||||
unmapfile(corhdr, cormap);
|
||||
mapfile(hdr, addr, cormap, nil);
|
||||
}
|
||||
if(syminit(hdr) < 0)
|
||||
fprint(2, "syminit %s: %\r", buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
38
src/libmach/elfnm.c
Normal file
38
src/libmach/elfnm.c
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <mach.h>
|
||||
#include <elf.h>
|
||||
|
||||
void
|
||||
usage(void)
|
||||
{
|
||||
fprint(2, "usage: elfnm file...\n");
|
||||
exits("usage");
|
||||
}
|
||||
|
||||
void
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
ElfSym esym;
|
||||
Fhdr *fp;
|
||||
int i, j;
|
||||
|
||||
ARGBEGIN{
|
||||
default:
|
||||
usage();
|
||||
}ARGEND
|
||||
|
||||
if(argc == 0)
|
||||
usage();
|
||||
|
||||
for(i=0; i<argc; i++){
|
||||
if((fp = crackhdr(argv[i], OREAD)) == nil){
|
||||
fprint(2, "%s: %r\n", argv[i]);
|
||||
continue;
|
||||
}
|
||||
for(j=0; elfsym(fp->elf, j, &esym)>=0; j++)
|
||||
print("%s 0x%lux\n", esym.name, esym.value);
|
||||
uncrackhdr(fp);
|
||||
}
|
||||
exits(0);
|
||||
}
|
||||
49
src/libmach/pthread.c
Normal file
49
src/libmach/pthread.c
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
#include <u.h>
|
||||
#include <thread_db.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <errno.h>
|
||||
#include <sys/procfs.h> /* psaddr_t */
|
||||
#include <libc.h>
|
||||
#include <mach.h>
|
||||
|
||||
static char *tderrstr[] =
|
||||
{
|
||||
[TD_OK] "no error",
|
||||
[TD_ERR] "some error",
|
||||
[TD_NOTHR] "no matching thread found",
|
||||
[TD_NOSV] "no matching synchronization handle found",
|
||||
[TD_NOLWP] "no matching light-weight process found",
|
||||
[TD_BADPH] "invalid process handle",
|
||||
[TD_BADTH] "invalid thread handle",
|
||||
[TD_BADSH] "invalid synchronization handle",
|
||||
[TD_BADTA] "invalid thread agent",
|
||||
[TD_BADKEY] "invalid key",
|
||||
[TD_NOMSG] "no event available",
|
||||
[TD_NOFPREGS] "no floating-point register content available",
|
||||
[TD_NOLIBTHREAD] "application not linked with thread library",
|
||||
[TD_NOEVENT] "requested event is not supported",
|
||||
[TD_NOEVENT] "requested event is not supported",
|
||||
[TD_NOCAPAB] "capability not available",
|
||||
[TD_DBERR] "internal debug library error",
|
||||
[TD_NOAPLIC] "operation is not applicable",
|
||||
[TD_NOTSD] "no thread-specific data available",
|
||||
[TD_MALLOC] "out of memory",
|
||||
[TD_PARTIALREG] "not entire register set was read or written",
|
||||
[TD_NOXREGS] "X register set not available for given threads",
|
||||
[TD_TLSDEFER] "thread has not yet allocated TLS for given module",
|
||||
[TD_VERSION] "version mismatch twixt libpthread and libthread_db",
|
||||
[TD_NOTLS] "there is no TLS segment in the given module",
|
||||
};
|
||||
|
||||
static char*
|
||||
terr(int e)
|
||||
{
|
||||
static char buf[50];
|
||||
|
||||
if(e < 0 || e >= nelem(tderrstr) || tderrstr[e] == nil){
|
||||
snprint(buf, sizeof buf, "thread err %d", e);
|
||||
return buf;
|
||||
}
|
||||
return tderrstr[e];
|
||||
}
|
||||
|
||||
269
src/libmach/t.c
Normal file
269
src/libmach/t.c
Normal file
|
|
@ -0,0 +1,269 @@
|
|||
#include <u.h>
|
||||
#include <thread_db.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <errno.h>
|
||||
#include <sys/procfs.h> /* psaddr_t */
|
||||
#include <libc.h>
|
||||
#include <mach.h>
|
||||
#include "ureg386.h"
|
||||
|
||||
int td_get_allthreads(td_thragent_t *ta, td_thrhandle_t **pall);
|
||||
|
||||
static char *tderrstr[] =
|
||||
{
|
||||
[TD_OK] "no error",
|
||||
[TD_ERR] "some error",
|
||||
[TD_NOTHR] "no matching thread found",
|
||||
[TD_NOSV] "no matching synchronization handle found",
|
||||
[TD_NOLWP] "no matching light-weight process found",
|
||||
[TD_BADPH] "invalid process handle",
|
||||
[TD_BADTH] "invalid thread handle",
|
||||
[TD_BADSH] "invalid synchronization handle",
|
||||
[TD_BADTA] "invalid thread agent",
|
||||
[TD_BADKEY] "invalid key",
|
||||
[TD_NOMSG] "no event available",
|
||||
[TD_NOFPREGS] "no floating-point register content available",
|
||||
[TD_NOLIBTHREAD] "application not linked with thread library",
|
||||
[TD_NOEVENT] "requested event is not supported",
|
||||
[TD_NOEVENT] "requested event is not supported",
|
||||
[TD_NOCAPAB] "capability not available",
|
||||
[TD_DBERR] "internal debug library error",
|
||||
[TD_NOAPLIC] "operation is not applicable",
|
||||
[TD_NOTSD] "no thread-specific data available",
|
||||
[TD_MALLOC] "out of memory",
|
||||
[TD_PARTIALREG] "not entire register set was read or written",
|
||||
[TD_NOXREGS] "X register set not available for given threads",
|
||||
[TD_TLSDEFER] "thread has not yet allocated TLS for given module",
|
||||
[TD_VERSION] "version mismatch twixt libpthread and libthread_db",
|
||||
[TD_NOTLS] "there is no TLS segment in the given module",
|
||||
};
|
||||
|
||||
static char*
|
||||
terr(int e)
|
||||
{
|
||||
static char buf[50];
|
||||
|
||||
if(e < 0 || e >= nelem(tderrstr) || tderrstr[e] == nil){
|
||||
snprint(buf, sizeof buf, "thread err %d", e);
|
||||
return buf;
|
||||
}
|
||||
return tderrstr[e];
|
||||
}
|
||||
|
||||
void
|
||||
usage(void)
|
||||
{
|
||||
fprint(2, "usage: t pid\n");
|
||||
exits("usage");
|
||||
}
|
||||
|
||||
#define STRINGSZ 128
|
||||
|
||||
/*
|
||||
* print the value of dot as file:line
|
||||
*/
|
||||
void
|
||||
printsource(long dot)
|
||||
{
|
||||
char str[STRINGSZ];
|
||||
|
||||
if (fileline(dot, str, STRINGSZ) >= 0)
|
||||
print("%s", str);
|
||||
}
|
||||
|
||||
void
|
||||
printlocals(Symbol *fn, Regs *regs)
|
||||
{
|
||||
int i;
|
||||
u32int v;
|
||||
Symbol s;
|
||||
|
||||
for (i = 0; indexlsym(fn, i, &s)>=0; i++) {
|
||||
if (s.class != CAUTO)
|
||||
continue;
|
||||
if(lget4(cormap, regs, s.loc, &v) >= 0)
|
||||
print("\t%s.%s/\t%#lux\n", fn->name, s.name, v);
|
||||
else
|
||||
print("\t%s.%s/\t?\n", fn->name, s.name);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
printparams(Symbol *fn, Regs *regs)
|
||||
{
|
||||
int i;
|
||||
Symbol s;
|
||||
u32int v;
|
||||
int first = 0;
|
||||
ulong pc, sp, bp;
|
||||
|
||||
if(0) print("pc=%lux sp=%lux bp=%lux ",
|
||||
(rget(regs, "PC", &pc), pc),
|
||||
(rget(regs, "SP", &sp), sp),
|
||||
(rget(regs, "BP", &bp), bp));
|
||||
for (i = 0; indexlsym(fn, i, &s)>=0; i++) {
|
||||
if (s.class != CPARAM)
|
||||
continue;
|
||||
if (first++)
|
||||
print(", ");
|
||||
if(0) print("(%d.%s.%ux.%x)", s.loc.type, s.loc.reg, s.loc.addr, s.loc.offset);
|
||||
if(lget4(cormap, regs, s.loc, &v) >= 0)
|
||||
print("%s=%#lux", s.name, v);
|
||||
else
|
||||
print("%s=?", s.name);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* callback on stack trace
|
||||
*/
|
||||
static int
|
||||
xtrace(Map *map, Regs *regs, ulong pc, ulong nextpc, Symbol *sym, int depth)
|
||||
{
|
||||
char buf[512];
|
||||
|
||||
USED(map);
|
||||
print("\t");
|
||||
if(sym){
|
||||
print("%s(", sym->name);
|
||||
printparams(sym, regs);
|
||||
print(")+0x%ux ", pc-sym->loc.addr);
|
||||
}else
|
||||
print("%#lux ", pc);
|
||||
printsource(pc);
|
||||
|
||||
print(" called from ");
|
||||
symoff(buf, 512, nextpc, CTEXT);
|
||||
print("%s ", buf);
|
||||
/* printsource(nextpc); */
|
||||
print("\n");
|
||||
if(sym)
|
||||
printlocals(sym, regs);
|
||||
return depth<40;
|
||||
}
|
||||
|
||||
void
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
struct ps_prochandle p;
|
||||
prgregset_t regs;
|
||||
int e;
|
||||
td_thragent_t *ta;
|
||||
td_thrhandle_t *ts;
|
||||
td_thrinfo_t info;
|
||||
int i, n;
|
||||
Ureg *u;
|
||||
UregRegs r;
|
||||
|
||||
ARGBEGIN{
|
||||
default:
|
||||
usage();
|
||||
}ARGEND
|
||||
|
||||
attachargs(argc, argv, OREAD);
|
||||
attachdynamic();
|
||||
|
||||
if(!corpid && !corhdr)
|
||||
sysfatal("could not attach to process");
|
||||
|
||||
p.pid = corpid;
|
||||
if((e = td_ta_new(&p, &ta)) != TD_OK)
|
||||
sysfatal("td_ta_new: %s", terr(e));
|
||||
if((e = td_ta_get_nthreads(ta, &n)) != TD_OK)
|
||||
sysfatal("td_ta_get_nthreads: %s", terr(e));
|
||||
print("%d threads\n", n);
|
||||
|
||||
if((n = td_get_allthreads(ta, &ts)) < 0)
|
||||
sysfatal("td_get_allthreads: %r");
|
||||
print("%d threads - regs = %p\n", n, regs);
|
||||
for(i=0; i<n; i++){
|
||||
if((e = td_thr_get_info(&ts[i], &info)) != TD_OK)
|
||||
sysfatal("td_thr_get_info: %s", terr(e));
|
||||
print("%d: startfunc=%lux stkbase=%lux pc=%lux sp=%lux lid=%d\n",
|
||||
i, info.ti_startfunc, info.ti_stkbase, info.ti_pc, info.ti_sp, info.ti_lid);
|
||||
if((e = td_thr_getgregs(&ts[i], regs)) != TD_OK)
|
||||
sysfatal("td_thr_getregs: %s", terr(e));
|
||||
print("%d: pc=%lux sp=%lux gs=%lux\n", i, regs[12], regs[15], regs[10]);
|
||||
if((u = _linux2ureg386((UregLinux386*)regs)) == nil)
|
||||
sysfatal("%r");
|
||||
r.r.rw = _uregrw;
|
||||
r.ureg = (uchar*)u;
|
||||
stacktrace(cormap, &r.r, xtrace);
|
||||
}
|
||||
exits(0);
|
||||
}
|
||||
|
||||
typedef struct AllThread AllThread;
|
||||
struct AllThread
|
||||
{
|
||||
td_thrhandle_t *a;
|
||||
int n;
|
||||
int err;
|
||||
};
|
||||
|
||||
static int
|
||||
thritercb(const td_thrhandle_t *th, void *cb)
|
||||
{
|
||||
td_thrhandle_t **p;
|
||||
AllThread *a;
|
||||
int n;
|
||||
|
||||
a = cb;
|
||||
if((a->n&(a->n-1)) == 0){
|
||||
if(a->n == 0)
|
||||
n = 1;
|
||||
else
|
||||
n = a->n<<1;
|
||||
if((p = realloc(a->a, n*sizeof a->a[0])) == 0){
|
||||
a->err = -1;
|
||||
return -1; /* stop iteration */
|
||||
}
|
||||
a->a = p;
|
||||
}
|
||||
a->a[a->n++] = *th;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
td_get_allthreads(td_thragent_t *ta, td_thrhandle_t **pall)
|
||||
{
|
||||
int e;
|
||||
AllThread a;
|
||||
|
||||
a.a = nil;
|
||||
a.n = 0;
|
||||
a.err = 0;
|
||||
if((e = td_ta_thr_iter(ta, thritercb, &a,
|
||||
TD_THR_ANY_STATE,
|
||||
TD_THR_LOWEST_PRIORITY,
|
||||
TD_SIGNO_MASK,
|
||||
TD_THR_ANY_USER_FLAGS)) != TD_OK){
|
||||
werrstr("%s", terr(e));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(a.err){
|
||||
free(a.a);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*pall = a.a;
|
||||
return a.n;
|
||||
}
|
||||
|
||||
/*
|
||||
td_err_e td_ta_map_id2thr(const td_thragent_t *ta_p, thread_t tid,td_thrhandle_t *th_p);
|
||||
*/
|
||||
|
||||
/*
|
||||
int
|
||||
threadregs(int tid, Regs **rp)
|
||||
{
|
||||
check pid
|
||||
look up tid (td_ta_map_id2thr)
|
||||
create Regs with thr handle inside
|
||||
rw function calls thr_getregs and then
|
||||
pulls out the desired register
|
||||
}
|
||||
|
||||
*/
|
||||
Loading…
Add table
Add a link
Reference in a new issue