LINUX.ORG.RU

Ответ на: комментарий от carrot

> Хотя попробуй.

"... пилите Шура, она же золотая ..." ;-)

carrot
()

О, извратился!

file1.c:

#include <stdio.h>

static void fun1(int aa)
{
printf("fun1:%d\n",aa);
}

file2.c:
#include <stdio.h>


void fun2(int aa)
{
return;
}

typedef void (*fun1_t)(int aa);

int main(void)
{
fun1_t fun=&fun2;

fun(20);


return 0;
}

gcc -c file1.c

(Все, больше file1.c трогать не будем)

gcc -o file2 file1.0 file2.c
gdb file2
(gdb) info functions
All defined functions:

Non-debugging symbols:
0x08048230  _init
0x08048258  __libc_start_main
0x08048268  printf
0x08048280  _start
0x080482a4  call_gmon_start
0x080482d0  __do_global_dtors_aux
0x08048310  frame_dummy
0x0804833c  fun2
0x08048342  main
0x08048370  fun1
0x08048390  __do_global_ctors_aux
0x080483c0  _fini
(gdb) q

Теперь мы знаем точку входа fun1 (0x08048370) 
Меняем file2.c:

#include <stdio.h>


void fun2(int aa)
{
return;
}

typedef void (*fun1_t)(int aa);

int main(void)
{
fun1_t fun=(fun1_t)0x08048370;

fun(20);


return 0;
}

gcc -o file2 file2.c file1.o

$./file2
fun1:20

Вуаля!

Изврат, конечно...

Die-Hard ★★★★★
()
Ответ на: комментарий от Pi

Pi (10.01.2005 21:39:10):

>>(Все, больше file1.c трогать не будем)

>это и есть самое паршивое в этом методе :)

Однако, это ВХОДИТ В УСЛОВИЕ ЗАДАЧИ!

Die-Hard ★★★★★
()
Ответ на: комментарий от cpu

cpu (10.01.2005 21:40:43):

>>Изврат, конечно...

>Да не то слово, ты зачем плохому учишь ?

Просто демонстрация возможности ТЕОРЕТИЧЕСКИ решить задачу.

Прошу заметить, предложенный метод IMHO будет работать на большинстве современных платформ/компиляторов -- разумеется, без каких-дибо гарантий. Я специально написал программу для вычисления точки входа так, чтобы ничего не менялось при подстановке "всамделишной" функции. Конечно, малейшие оптимизации могут все порушить (а могут и НЕ порушить!).

2CL (10.01.2005 19:06:34):

Разумеется, исходная задача, строго говоря, решения не имеет. Никогда так не делай, если не до конца понимаешь все, что я понаписАл :-)

Die-Hard ★★★★★
()
Ответ на: комментарий от Die-Hard

> Разумеется, исходная задача, строго говоря, решения не имеет

ну, почему же? Ведь gdb, как-то находит "0x08048370 fun1"?
Т.е., наверное, можно "встроенный в file2 gdb" как-то написать (??)

++
вообще, интерсно, как gdb это делает?

carrot
()
Ответ на: комментарий от carrot

carrot (10.01.2005 23:09:24):

>...наверное, можно "встроенный в file2 gdb" как-то написать (??)

Это будет "компиляторно-зависимо". Именно это я имел в виду, когда писАл "...исходная задача, строго говоря, решения не имеет".

Из условия непонятно, почему нельзя менять file1.c.

Дан только объектный файл с прототипами? Или по условиям лицензии нельзя ничего менять в исходниках? В последнем случае -- а перекомпилировать его можно любым компилятором? В первом случае -- а каким компилятором был скомпилирован объектник? etc.

Die-Hard ★★★★★
()
Ответ на: комментарий от Die-Hard

> вообще, интерсно, как gdb это делает?

хотя, приблизительно, понятно как ...
анализируется elf format и т.д. ...

Слабо, вариант без gdb? ;-)

carrot
()
Ответ на: комментарий от carrot

carrot (10.01.2005 23:22:10):

> Слабо, вариант без gdb? ;-)

Да легко! За день, думаю, слабАю (если гугль будет) -- только зачем? Не зря ж люди всякие gdb и objdump'ы понаписАли...

Die-Hard ★★★★★
()
Ответ на: комментарий от carrot

BTW, вот еще тупое решение:

---------- file2.c ----------

#include "file1.c"

void fun2() {
   fun(0xdeadcafe);
}

-----------------------------

2CL: Конечно, так тоже делать не надо, но все же ИМХО
лучше, чем вычислять адрес fun :)

jek_
()
Ответ на: комментарий от jek_

Ну а если и файл file1.c компилируется, то чтобы избежать ошибок
с дублированием символов, можно попробовать поизвращаться, типа

#define fun fun_0
#include "file1.c"
void fun2() {
   fun(0xdeadcafe);
} 
#undef fun

или засунуть fileN.c в shared library N... В таком духе :)

jek_
()
Ответ на: комментарий от jek_

ой, вот сейчас сообразил, что все это не будет работаеть, если fun использует глобалы/static переменные... :(

jek_
()

может быть лучше

cp file1.c file1.tmp.c && echo "void tmp_fun1 (int aa) {fun1 (aa);}" >> file1.tmp.c && gcc -o file1.o -c file1.tmp.c

и вызывай наздоровье через tmp_fun1... file1.c ведь никак не изменился?

bugmaker ★★★★☆
()
Ответ на: комментарий от bugmaker

пробежался вчера, по gdb сырцам ..
Впечатляет. Вдохнавляет. Там и elf-parcer, и C++ demangler ..
Было бы неплохо иметь что-то типа libgdb (то, что называется http://sources.redhat.com/gdb/papers/libgdb2/libgdb.html,
на самом деле не совсем то).

Еще, было бы интересно посмотреть на то, что получилось бы
от скрещивания gdb с CINTом (http://root.cern.ch/root/Cint.html).
Ведь многие вещи просто пересекаются ...

carrot
()
Ответ на: комментарий от jek_

2jek_ :

Насколько я понял, исходники file1.c недоступны. Есть только объектный файл и прототипы.

Die-Hard ★★★★★
()

> static void fun1(int aa)
> {
> }
>
> возможно ли к ней обратиться из файла file2.c ?
> file1.c изменить не могу.

Компилируй gcc -Dstatic= file1.c file2.c -o file.exe, и все сбудется - нету больше никаких static ;)

murla
()
Ответ на: комментарий от carrot

> и C++ demangler ..

Дык это модно видимо ...

gdb - свой c++filt - свой libstdc++ - тоже свой

sS ★★★★★
()
Ответ на: комментарий от murla

2murla (*) (11.01.2005 15:03:15)

дык #include "file1.c" её и все дела ;)

sS ★★★★★
()
Ответ на: комментарий от murla

murla (11.01.2005 15:03:15):

> Компилируй gcc -Dstatic= file1.c file2.c

Это эквивалентно изменению file1.c, что запрещено условиями задачи.

cat file1.c|sed 's/static//g'>tmp.c
gcc tmp.c file2.c
rm tmp.c

Или еше проще:

cp file1.c tmp.c
emacs tmp.c
Убираем в нужном месте слово static
gcc tmp.c file2.c

Die-Hard ★★★★★
()
Ответ на: комментарий от Die-Hard

> Или по условиям лицензии нельзя ничего менять в исходниках?

О, а вот интересно - при _этих_ условиях можно применять ключ `-D'? :-))

murla
()
Ответ на: комментарий от Die-Hard

Вредно, конечно, помогать кул-хацкерам, но ...

$ more func1.c
static int func5()
{
return 0xdeadbeef;
}
static int func1()
{
return 0xdeadbeef;
}
$ gcc -c func1.c

Итак код утерян :-(

$ nm func1.o
0000000a t func1 - функция видна.
00000000 t func5
$ more lds
SECTIONS {
.text : {
func1 = . + 0xa; - не зря мы запускали nm :-)
*(.text)
}
.data : { *(.data) }
.bss : { *(.bss) }
.comment : { *(.comment) }
}
$ ld -r -T lds -o func3.o func1.o
$ nm func3.o
0000000a t func1
0000000a T func1 - есть светлые моменты в жизни :-)
00000000 t func5

Теперь о мучениях с func1.o можно забыть

$ gcc -o main main.c func3.o
$ ./main
0xdeadbeef - вай работает

func1.o так и остался немым:

$ gcc -o main main.c func1.o
/tmp/ccQpSTL6.o(.text+0x11): In function `main':
: undefined reference to `func1'
collect2: ld returned 1 exit status

Мораль: учите матчасть

io ★★
()
Ответ на: комментарий от Die-Hard

А я думал отправить в FAQ, порекомендовать man/info
и учить матчасть являются на LOR-е признаками хорошего тона.
Процентов дцать таких ответов. И нервных мало.

Ну, извини, если что не так.

Однако, ей-бо перед чтением источников gdb лучше пройтись
по описанию объектных/выполняемых файлов и ld. Они короче ...

А то, что подобные вопросы интересует в основном кул-хацкеров
- это факт.
Можно просто пройтись сначала по вопросам подобного рода,
а потом по тем же авторам в других рубриках - вопрос "зачем"
иногда сразу отпадает.

Примеры приводить не буду, а то опять флейм будет ...

io ★★
()
Ответ на: комментарий от io

2io

Это банально. По-большому, ты повторил, тоже, что делает gdb,
но другими средствами:
nm = elf-parser + demangler (который здесь не используется)
ld - то же делает и gdb

--------------------------------------------
Вообще задача стоит
"не из shella, a из программы (без nm, gdb)", и
допустим, "под виндами" ...

Хотя, спасибо. Век живи, век учись ...

carrot
()
Ответ на: комментарий от carrot

>Однако, ей-бо перед чтением источников gdb лучше пройтись
>по описанию объектных/выполняемых файлов

именно, поэтому, и смотрелись исходники
- там тебе и описание, и алгоритм

Поверь, как раз это, кратчайший путь

carrot
()
Ответ на: комментарий от carrot

>Вообще задача стоит
>"не из shella, a из программы (без nm, gdb)", и
>допустим, "под виндами" ...

для меня, прежде всего, эта задача очень интересна в контексте
C/C++ интерпретатора, который мы разрабатываем
http://root.cern.ch/root/Cint.html

В настоящий момент, для того, чтобы иметь доступ к
"pointers to functions" находящихся в DLL библиотеке
CINT использует технику отличную от gdb, а именно он
генерит dictionary (свой собстевенный mangler) на основе headers files.
В этом есть свои преимущества - компилятор-независимость,
object/DLL file format независимость и пр.

Но, в то же время - это ограничивает его применение,
он не может взять произвольную DLL, как gdb.

Именно поэтому gdb sources, опыт - очень интересны!

Думаю, поднять и обсудить в команде возможность реализации
"gdb approach" в CINTe в ближайшее время.


carrot
()
Ответ на: комментарий от carrot

"ой, Маша, я фииигею! - я не Маша. - а я все равно фиигею!

Поражает, польза от попытки найти ответ на дурацкий ворос ...

++

запустил flame внутри команды ;о)

carrot
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.