Nikolay Igotti

pageicon Tuesday Jun 19, 2007

Context sensitive function behavior

Usually C, unlike dynamic languages, considered not so easy to write context sensitive code. To demonstrate that this is feasible, at least on some systems and compilers I wrote following hack. Function foxy() behaves differently depending on who called it. This behavior could be useful in profilers, and some modularity checks (for example if you want to ensure noone calls your static functions even by pointers).
#include <elf.h>
#include <stdio.h>
#include <stdint.h>

typedef struct {
  intptr_t start;
  intptr_t end;
  char* value;
} range_t;


static range_t ranges[2];

int compute_size(void* start) {
  Dl_info dlip;
  Elf32_Sym* sym = 0;
  int rv = dladdr1(start, &dlip, (void**)&sym, RTLD_DL_SYMENT);
  
  return (rv && sym) ? sym->st_size : -1;
}

void init_ranges() {
  int i;

  ranges[0].start = (intptr_t)&foo;
  ranges[0].value = "foo";
  ranges[1].start = (intptr_t)&bar;
  ranges[1].value = "bar";

  for (i=0; i < sizeof(ranges)/sizeof(ranges[0]); i++) {
    int sz = compute_size((void*)ranges[i].start);
    if (sz < 0) {
      sz = 0;
    }
    ranges[i].end = ranges[i].start + sz;
  }
}
 

char* foxy() {
  intptr_t caller = (intptr_t)__builtin_return_address (0);
  int i, idx = -1;
  
  for (i=0; i < sizeof(ranges)/sizeof(ranges[0]); i++) {
    if (caller >= ranges[i].start && caller < ranges[i].end) {
      idx = i;
      break;
    }
  }
  

   if (idx != -1) {
    return ranges[i].value;
  }

  return "other";
}


void foo() {
  printf("foo=%s\n", foxy());
}

void bar() {
  printf("bar=%s\n", foxy());
}

void boo() {
  printf("boo=%s\n", foxy());
}




int main() {
  init_ranges();
  foo();
  bar();
  boo();
  return 0;
}
Comments:

Post a Comment:
  • HTML Syntax: NOT allowed

« December 2009
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
  
       
Today

Feeds

Search this blog

Links

Weblog menu

Today's referrers

Today's Page Hits: 132

Stats