[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-optimize
Subject: Re: Dynamic symbol table
From: Karl Vogel <karl.vogel () seagha ! com>
Date: 2004-07-21 11:16:52
Message-ID: 200407211316.52096.karl.vogel () seagha ! com
[Download RAW message or body]
Lubos Lunak wrote:
> On Tuesday 20 of July 2004 18:37, Karl Vogel wrote:
>>
>> X 08048520 0 X 008 paddr 08048000 acc 08048520 pgoff 00000000 foff
>> 00000000 fnam=/usr/bin/kedit A 002498a3 0 X 002 paddr 00432000 acc
>> 004323f4 pgoff 00000000 foff 00000000 fnam=/usr/lib/libkdeinit_kedit.so A
>
> How did you get this? Is it some profiling tool? I don't see anything
> similar
> in /proc.
I wrote a quick 'n dirty hack to generate this. The tool definately needs to
TLC, but anyway I'll attach it.
Build it with (Makefile):
---
tracer: tracer.c
$(CC) -Wall -Os -shared -o tracer tracer.c -ldl
---
Usage is:
LD_PRELOAD=./tracer executable
Output will go to stderr. The tool assumes it's in /home somewhere, so it
doesn't mprotect stuff that lives in /home -- ie. as to not block itself :)
Either way.. a valgrind based execution flow tracer would be nicer, but this
kind of works also. (on Fedora Core 2)
> Not everything from the file is supposed to be loaded when executing it.
> There may be debug data or similar. If you run 'objdump --headers' on the
> file, find first sections that is not marked LOAD, and its file offset
> column gives in hex how much of the file is actually loaded. (If you just
> strip the file it gives almost the same number.)
Yups.. was aware of this.. otherwise I don't think my KDE would load this
fast, seeing that my libqt is 63Mb :)
btw: 'readelf -e executable' also works.. and the output is more readable
["tracer.c" (text/x-csrc)]
/*
* Crude LD_PRELOAD hack to show which pages are faulted
* during execution.
*
* Usage:
* LD_PRELOAD=./tracer executable
*
* Output of the tracer is to stderr.
*
* The tracer has to be in /home somewhere (hey I said it
* was crude.. didn't I!).
*
* Author: Karl Vogel
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <signal.h>
#include <string.h>
#include <dlfcn.h>
#define __USE_GNU
#include <sys/ucontext.h>
#include <unistd.h>
#include <errno.h>
static void init (void) __attribute__ ((constructor));
static __sighandler_t (*libc_signal) (int __sig, __sighandler_t __handler);
extern int __sigaction(int __sig, __const struct sigaction *__restrict __act,
struct sigaction *__restrict __oact);
#define MAXMAPS 200
static struct map {
unsigned long start;
unsigned long end;
char name[256];
int prot;
unsigned long pgoff;
} maps[MAXMAPS];
static int mapcount;
static int findmap(void *addr)
{
unsigned long vmaddr= (unsigned long)addr;
int i;
int rv= -1;
for (i= 0; i<mapcount; i++) {
if ( vmaddr >= maps[i].start && vmaddr <= maps[i].end) {
rv= i;
break;
}
}
if (rv == -1) {
fprintf(stderr, "E SEGV_MAPERR in unknown range!\n");
abort();
}
return rv;
}
static void mysig(int signum, siginfo_t *si,
void *vuc)
{
static unsigned long oldaddr= 0;
unsigned long addr;
int i;
ucontext_t *uc= (ucontext_t *)vuc;
char type;
switch(si->si_code) {
case SEGV_MAPERR:
fprintf(stderr, "Unhandled SEGV_MAPERR\n");
abort();
break;
case SEGV_ACCERR:
addr= (unsigned long)si->si_addr;
addr &= ~(0x1000-1);
i= findmap(si->si_addr);
type = (uc->uc_mcontext.gregs[REG_EIP] != (unsigned int)si->si_addr)?'A':'X';
fprintf(stderr, "%c %08x %8lu X %03d paddr %08lx acc %08lx pgoff %08lx foff %08lx fnam=%s\n",
type,
uc->uc_mcontext.gregs[REG_EIP],
maps[i].pgoff + addr-maps[i].start,
i,
addr,
(unsigned long)si->si_addr,
maps[i].pgoff,
maps[i].pgoff + addr-maps[i].start,
maps[i].name
);
if (mprotect((void *)addr, 0x1000, maps[i].prot)==-1) {
perror("mprotect");
abort();
}
break;
default:
fprintf(stderr, "signum %d si_code= %d\n", signum, si->si_code);
abort();
break;
}
if (oldaddr == (unsigned long)si->si_addr) {
fprintf(stderr, "Double whammy!\n");
abort();
}
oldaddr= (unsigned long)si->si_addr;
}
__sighandler_t signal (int __sig, __sighandler_t __handler)
{
switch(__sig) {
case SIGFPE:
case SIGSEGV:
case SIGILL:
case SIGABRT:
case SIGBUS:
fprintf(stderr, "E trying to set signal %d -- Ignoring!!!\n", __sig);
break;
default:
return libc_signal(__sig, __handler);
break;
}
return SIG_ERR;
}
int sigaction(int __sig, __const struct sigaction *__restrict __act,
struct sigaction *__restrict __oact)
{
switch(__sig) {
case SIGFPE:
case SIGSEGV:
case SIGILL:
case SIGABRT:
case SIGBUS:
fprintf(stderr, "E trying to set sigaction %d -- Ignoring!!!\n", __sig);
break;
default:
return __sigaction(__sig, __act, __oact);
break;
}
errno= EINVAL;
return 0;
}
static void init(void)
{
struct sigaction sa = {
.sa_sigaction = mysig,
.sa_flags = SA_SIGINFO | SA_RESTART
};
FILE *fp;
char buf[256];
unsigned long vm_start, vm_end;
char read,write,share,exec;
unsigned long pgoff;
unsigned long vm_size;
int skip;
unsigned long inode;
memset((char *)maps, 0, sizeof(maps));
mapcount= 0;
sigemptyset(&sa.sa_mask);
if (__sigaction(SIGSEGV, &sa, 0) < 0)
return;
fp= fopen("/proc/self/maps", "r");
if (!fp) {
perror("fopen");
abort();
}
while(fgets(buf, sizeof(buf), fp)) {
sscanf(buf, "%08lx-%08lx %c%c%c%c %08lx %02x:%02x %lu",
&vm_start,&vm_end, &read,&write,&exec,&share,
&pgoff, &skip, &skip, &inode);
if (inode==0)
continue;
buf[strlen(buf)-1]= 0;
/*
* Lookup the signal() symbol in the currently mapped
* libc, as it's not exported like __sigaction is.
*/
if (strstr(&buf[49], "libc")) {
void *handle= dlopen(&buf[49], RTLD_LAZY);
if (!handle) {
fprintf(stderr, "dlopen: %s", dlerror());
abort();
}
libc_signal= dlsym(handle, "signal");
if (!handle) {
fprintf(stderr, "dlsym: %s", dlerror());
abort();
}
/*
* Don't trap on myself (installed in /home) or on the libraries
* that contain the functions I'm using here (/lib)
*/
} else if ( exec == 'x' &&
buf[49] == '/' &&
strncmp(&buf[49], "/lib/", 5) &&
strncmp(&buf[49], "/home", 5)
) {
vm_size= vm_end-vm_start;
maps[mapcount].start= vm_start;
maps[mapcount].end= vm_end;
maps[mapcount].pgoff= pgoff;
maps[mapcount].prot= 0;
if (read=='r')
maps[mapcount].prot |= PROT_READ;
if (write=='w')
maps[mapcount].prot |= PROT_WRITE;
if (exec=='x')
maps[mapcount].prot |= PROT_EXEC;
strcpy(maps[mapcount].name, &buf[49]);
mapcount++;
if (mprotect((void *)vm_start, vm_size, PROT_NONE) == -1) {
perror("mprotect");
abort();
}
}
}
fclose(fp);
fprintf(stderr, "INIT:%d\n", getpid());
}
_______________________________________________
Kde-optimize mailing list
Kde-optimize@kde.org
https://mail.kde.org/mailman/listinfo/kde-optimize
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic