Как добавить вызов функции, чтобы другие символы стали undefined при связывании?
Я надеюсь, что кто-то сможет помочь устранить проблему, которая, по моему мнению, является проблемой компоновщика script.
У меня возникает странная проблема после добавления вызова к новой функции. Однако без вызова функции мои объектные файлы ссылаются правильно, однако при добавлении нового вызова функции я получаю ссылку undefined на символ из другого объектного файла (я проверял, что он действительно присутствует с использованием objdump).
Также странно, если присутствует вызов функции, если я сначала свяжу все объектные файлы с помощью ld -r (чтобы получить перемещаемый вывод), а затем используя мою ссылку script, ссылок undefined нет, но кажется ссылка script игнорируется, поскольку выходной двоичный файл не имеет правильной точки входа.
Мой (кросс-компилятор) ld версия:
i586-elf-ld --version
GNU ld (GNU Binutils) 2.20.1.20100303
Мои попытки доказать наличие "отсутствующего" символа:
> i586-elf-ld -T link.ld -o kernel32.bin kernel_loader.o main.o stdio.o common.o gdt.o gdt.bin -y putch
main.o: reference to putch
stdio.o: definition of putch
main.o: In function `main':
main.c:(.text+0x1f): undefined reference to `putch'
N.B. (когда я создал этот вывод, я использовал имя файла gdt.bin для сборщика ассемблеров nasm, это просто еще один файл .o).
Я вижу символ, который "отсутствует" в соответствующем объектном файле:
i586-elf-objdump -ht stdio.o
stdio.o: формат файла elf32-i386
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 000002f9 00000000 00000000 00000034 2**2
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
1 .data 0000000c 00000000 00000000 00000330 2**2
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00000008 00000000 00000000 0000033c 2**2
ALLOC
3 .comment 00000012 00000000 00000000 0000033c 2**0
CONTENTS, READONLY
SYMBOL TABLE:
00000000 l df *ABS* 00000000 stdio.c
00000000 l d .text 00000000 .text
00000000 l d .data 00000000 .data
00000000 l d .bss 00000000 .bss
00000000 l d .comment 00000000 .comment
00000000 g F .text 00000016 strlen
00000016 g F .text 0000005c scroll
00000008 g O .data 00000004 numrows
00000004 g O .bss 00000004 ypos
00000004 g O .data 00000004 numcols
00000004 O *COM* 00000004 screen_mem
00000000 *UND* 00000000 memcpy
00000000 *UND* 00000000 memsetw
00000072 g F .text 0000007d newline
00000000 g O .bss 00000004 xpos
000000ef g F .text 0000002e writech
00000000 g O .data 00000004 colour
0000011d g F .text 00000061 cls
0000017e g F .text 00000010 init_video
0000018e g F .text 00000133 putch
000002c1 g F .text 00000037 puts
000002f8 g F .text 00000001 set_text_colour
И объектный файл с неразрешенной ссылкой:
i586-elf-objdump -ht main.o
main.o: file format elf32-i386
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 0000007f 00000000 00000000 00000034 2**2
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
1 .data 00000000 00000000 00000000 000000b4 2**2
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00000000 00000000 00000000 000000b4 2**2
ALLOC
3 .rodata.str1.1 00000024 00000000 00000000 000000b4 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
4 .comment 00000012 00000000 00000000 000000d8 2**0
CONTENTS, READONLY
SYMBOL TABLE:
00000000 l df *ABS* 00000000 main.c
00000000 l d .text 00000000 .text
00000000 l d .data 00000000 .data
00000000 l d .bss 00000000 .bss
00000000 l d .rodata.str1.1 00000000 .rodata.str1.1
00000000 l d .comment 00000000 .comment
00000000 g F .text 0000007f main
00000000 *UND* 00000000 init_video
00000000 *UND* 00000000 gdt_install
00000000 *UND* 00000000 putch
00000000 *UND* 00000000 puts
00000018 O *COM* 00000001 gdt
00000006 O *COM* 00000001 gdtp
Моя ссылка script (не уверен, что это будет актуально):
OUTPUT_FORMAT("binary")
ENTRY(start)
phys = 0x00100000;
SECTIONS
{
.text phys : AT(phys) {
code = .;
*(.text)
*(.rodata*)
. = ALIGN(4096);
}
.data . : AT(data)
{
data = .;
*(.data)
. = ALIGN(4096);
}
.bss . : AT(bss)
{
bss = .;
*(.bss)
. = ALIGN(4096);
}
end = .;
}
Если я прокомментирую вызов putch в main.c, я вместо этого получаю undefined ссылки на puts... если я удалю вызов gdt_install, никаких ошибок!
gdt_install находится в файле C, но gdt_install вызывает функцию, определенную в gdt.asm.
void gdt_install() {
/* ... */
gdt_reset();
}
[bits 32]
[section .text]
global gdt_reset
extern gdtp
gdt_reset:
lgdt [gdtp]
mov ax, 0x10 ; 0x10 offset for data segment (sizeof(struct gdt_entry) * 2)
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
jmp 0x08:gdt_reset2 ; 0x08 offset for code segment (sizeof(struct gdt_entry))
gdt_reset2:
ret ; ret back to C
Чтобы попытаться и дальше диагностировать причину, я играл вокруг попытки воссоздать ошибки. Если я переведу вызов функции gdt_install() в определенное место в исходном коде, я не получаю никаких ошибок, и все работает нормально:
int main() {
init_video();
putch('A');
puts("<- print a single char there...\n");
gdt_install();
puts("asdf\n\n");
int i;
for (i = 0; i < 15; ++i) {
if (i % 2 == 0) {
puts("even\n");
} else {
puts("odd\n");
}
}
return 0;
}
Если я переведу вызов выше первого вызова puts(), я получаю undefined ссылки для puts!:
...
init_video();
putch('A');
gdt_install();
puts("<- print a single char there...\n");
puts("asdf\n\n");
...
i586-elf-ld -T link.ld -o kernel32.bin kernel_loader.o main.o stdio.o common.o gdt.o gdt_asm.o
main.o: In function `main':
main.c:(.text+0x2b): undefined reference to `puts'
main.c:(.text+0x37): undefined reference to `puts'
main.c:(.text+0x51): undefined reference to `puts'
main.c:(.text+0x63): undefined reference to `puts'
Затем, если я переведу вызов выше putch(), он вызывает ссылку undefined putch (которая была там, где я первоначально имел вызов):
...
init_video();
gdt_install();
putch('A');
puts("<- print a single char there...\n");
puts("asdf\n\n");
...
main.o: In function `main':
main.c:(.text+0x1f): undefined reference to `putch'
И, наконец, над init_video() вызывает ссылку undefined на init_video:
...
gdt_install();
init_video();
putch('A');
puts("<- print a single char there...\n");
puts("asdf\n\n");
...
main.o: In function `main':
main.c:(.text+0x15): undefined reference to `init_video'
Что вызывает эта ошибка? Он, как вызов gdt_install, как-то "развращает" другие символы... Я не мог найти никакой ссылки на него в каких-либо документах, но есть ли способ, которым вызов функции gdt_install может привести к перерасходу, "границе" линкера, развращению другой код?
Кто-нибудь сталкивался с такой проблемой или имел какие-либо идеи относительно дальнейшего расследования? Я опубликовал на форуме osdev: http://forum.osdev.org/viewtopic.php?f=1&t=22227, но не имел большой удачи.
Спасибо
Edit:
Я не уверен, что это актуально, но если я опускаю ссылку script при связывании, все предыдущие ошибки исчезают... (хотя, тогда мой загрузчик не может вызвать ядро, так как он не понимает двоичные файлы эльфа).
В соответствии с запросом здесь файл main.c до и после предварительной обработки и дизассемблирован из скомпилированного файла main.o.
перед предварительной обработкой:
#include <stdio.h>
#include <common.h>
#include <gdt.h>
int main() {
init_video();
putch('A');
gdt_install();
puts("<- print a single char there...\n");
puts("asdf\n\n");
int i;
for (i = 0; i < 15; ++i) {
if (i % 2 == 0) {
puts("even\n");
} else {
puts("odd\n");
}
}
return 0;
}
После предварительной обработки:
i586-elf-gcc -Wall -O -fstrength-reduce -fomit-frame-pointer -fno-inline -nostdinc -nostdlib -fsigned-char -nostartfiles -nodefaultlibs -fno-builtin -fno-stack-protector -I./include -E main.c
# 1 "main.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "main.c"
# 1 "./include/stdio.h" 1
# 1 "./include/common.h" 1
typedef unsigned short ushort;
typedef unsigned char uchar;
typedef unsigned int uint;
typedef unsigned long ulong;
typedef int size_t;
void *memcpy(void *dst, const void *src, size_t n);
void *memset(void *dst, const char val, size_t n);
void *memsetw(void *dst, const ushort val, size_t n);
void *memseti(void *dst, const int val, size_t n);
# 5 "./include/stdio.h" 2
void cls();
void writech(char c);
void putch(char c);
void puts(char *str);
void set_text_colour(uchar f, uchar b);
void init_video();
size_t strlen(char *str);
# 2 "main.c" 2
# 1 "./include/gdt.h" 1
struct gdt_entry {
ushort limit_low;
ushort base_low;
uchar base_middle;
uchar access;
uchar granularity;
uchar base_high;
} __attribute__((packed));
struct gdt_ptr {
ushort limit;
uint base;
} __attribute__((packed));
void gdt_set_gate(int n, ulong base, ulong limit, uchar access, uchar gran);
void gdt_install();
extern void gdt_reset();
# 4 "main.c" 2
int main() {
init_video();
putch('A');
gdt_install();
puts("<- print a single char there...\n");
puts("asdf\n\n");
int i;
for (i = 0; i < 15; ++i) {
if (i % 2 == 0) {
puts("even\n");
} else {
puts("odd\n");
}
}
return 0;
}
Изменить еще раз:
Спасибо, что предложили -g3 дать более хороший результат разборки:
main.o: file format elf32-i386
SYMBOL TABLE:
00000000 l df *ABS* 00000000 main.c
00000000 l d .text 00000000 .text
00000000 l d .data 00000000 .data
00000000 l d .bss 00000000 .bss
00000000 l d .rodata.str1.4 00000000 .rodata.str1.4
00000000 l d .rodata.str1.1 00000000 .rodata.str1.1
00000000 l d .stab 00000000 .stab
00000000 l d .stabstr 00000000 .stabstr
00000000 l d .comment 00000000 .comment
00000000 g F .text 0000007f main
00000000 *UND* 00000000 init_video
00000000 *UND* 00000000 putch
00000000 *UND* 00000000 gdt_install
00000000 *UND* 00000000 puts
Disassembly of section .text:
00000000 <main>:
#include <stdio.h>
#include <common.h>
#include <gdt.h>
int main() {
0: 8d 4c 24 04 lea 0x4(%esp),%ecx
4: 83 e4 f0 and $0xfffffff0,%esp
7: ff 71 fc pushl -0x4(%ecx)
a: 55 push %ebp
b: 89 e5 mov %esp,%ebp
d: 53 push %ebx
e: 51 push %ecx
init_video();
f: e8 fc ff ff ff call 10 <main+0x10>
putch('A');
14: 83 ec 0c sub $0xc,%esp
17: 6a 41 push $0x41
19: e8 fc ff ff ff call 1a <main+0x1a>
gdt_install();
1e: e8 fc ff ff ff call 1f <main+0x1f>
puts("<- print a single char there...\n");
23: c7 04 24 00 00 00 00 movl $0x0,(%esp)
2a: e8 fc ff ff ff call 2b <main+0x2b>
puts("asdf\n\n");
2f: c7 04 24 00 00 00 00 movl $0x0,(%esp)
36: e8 fc ff ff ff call 37 <main+0x37>
3b: 83 c4 10 add $0x10,%esp
int i;
for (i = 0; i < 15; ++i) {
3e: bb 00 00 00 00 mov $0x0,%ebx
if (i % 2 == 0) {
43: f6 c3 01 test $0x1,%bl
46: 75 12 jne 5a <main+0x5a>
puts("even\n");
48: 83 ec 0c sub $0xc,%esp
4b: 68 07 00 00 00 push $0x7
50: e8 fc ff ff ff call 51 <main+0x51>
55: 83 c4 10 add $0x10,%esp
58: eb 10 jmp 6a <main+0x6a>
} else {
puts("odd\n");
5a: 83 ec 0c sub $0xc,%esp
5d: 68 0d 00 00 00 push $0xd
62: e8 fc ff ff ff call 63 <main+0x63>
67: 83 c4 10 add $0x10,%esp
puts("asdf\n\n");
int i;
for (i = 0; i < 15; ++i) {
6a: 43 inc %ebx
6b: 83 fb 0f cmp $0xf,%ebx
6e: 75 d3 jne 43 <main+0x43>
puts("odd\n");
}
}
return 0;
}
70: b8 00 00 00 00 mov $0x0,%eax
75: 8d 65 f8 lea -0x8(%ebp),%esp
78: 59 pop %ecx
79: 5b pop %ebx
7a: 5d pop %ebp
7b: 8d 61 fc lea -0x4(%ecx),%esp
7e: c3 ret
И теперь новый вывод из чистого make:
$ make
nasm -f elf kernel_loader.asm -o kernel_loader.o
i586-elf-gcc -Wall -O0 -fstrength-reduce -fomit-frame-pointer -fno-inline -nostdinc -nostdlib -fsigned-char -nostartfiles -nodefaultlibs -fno-builtin -fno-stack-protector -I./include -g3 -c main.c
i586-elf-gcc -Wall -O0 -fstrength-reduce -fomit-frame-pointer -fno-inline -nostdinc -nostdlib -fsigned-char -nostartfiles -nodefaultlibs -fno-builtin -fno-stack-protector -I./include -g3 -c stdio.c
i586-elf-gcc -Wall -O0 -fstrength-reduce -fomit-frame-pointer -fno-inline -nostdinc -nostdlib -fsigned-char -nostartfiles -nodefaultlibs -fno-builtin -fno-stack-protector -I./include -g3 -c common.c
i586-elf-gcc -Wall -O0 -fstrength-reduce -fomit-frame-pointer -fno-inline -nostdinc -nostdlib -fsigned-char -nostartfiles -nodefaultlibs -fno-builtin -fno-stack-protector -I./include -g3 -c gdt.c
nasm -f elf gdt.asm -o gdt_asm.o
i586-elf-ld -T link.ld -o kernel32.bin -\( kernel_loader.o main.o stdio.o common.o gdt.o gdt_asm.o -\)
main.o: In function `main':
/cygdrive/c/programming/os/kernel/main.c:12: undefined reference to `puts'
/cygdrive/c/programming/os/kernel/main.c:14: undefined reference to `puts'
/cygdrive/c/programming/os/kernel/main.c:20: undefined reference to `puts'
/cygdrive/c/programming/os/kernel/main.c:22: undefined reference to `puts'
make: *** [kernel32.bin] Error 1
Изменить 3
В соответствии с запросом здесь вывод nm -s на stdio.o
i586-elf-nm -s stdio.o
00000042 T cls
00000000 D colour
00000000 T init_video
U memcpy
U memsetw
0000015e T newline
00000004 D numcols
00000008 D numrows
000001e4 T putch
0000024e T puts
00000004 C screen_mem
000000b8 T scroll
00000291 T set_text_colour
00000016 T strlen
00000199 T writech
00000000 B xpos
00000004 B ypos
Изменить 4
В соответствии с запросом здесь представлены все исходные файлы. Я загрузил файлы в zip, чтобы: http://www.owenstephens.co.uk/media/files/kernel.zip Спасибо за постоянный интерес и помощь, это очень ценится!
Makefile
NASM=nasm
GCC=i586-elf-gcc
LD=i586-elf-ld
FMT=-f elf
GFLAGS=-Wall -O0 -fstrength-reduce -fno-inline -nostdinc -nostdlib -fsigned-char -nostartfiles -nodefaultlibs -fno-builtin -fno-stack-protector -I./include -g3 -c
LFLAGS=-T link.ld
ALL=kernel_loader.o main.o stdio.o common.o gdt.o gdt_asm.o
INCLUDES=include/stdio.h include/common.h include/gdt.h
all: $(ALL) kernel32.bin
kernel_loader.o: kernel_loader.asm
$(NASM) $(FMT) $*.asm -o [email protected]
main.o: main.c
$(GCC) $(GFLAGS) $<
stdio.o: stdio.c include/stdio.h
$(GCC) $(GFLAGS) $<
common.o: common.c include/common.h
$(GCC) $(GFLAGS) $<
gdt.o: gdt.c include/gdt.h
$(GCC) $(GFLAGS) $<
gdt_asm.o: gdt.asm
$(NASM) $(FMT) $< -o [email protected]
kernel32.bin: $(ALL) $(INCLUDES)
$(LD) $(LFLAGS) -o [email protected] -\( $(ALL) -\)
clean:
rm -f $(ALL) kernel32.bin
Ссылка script:
OUTPUT_FORMAT("binary")
ENTRY(_start)
phys = 0x00100000;
SECTIONS
{
.text phys : AT(phys) {
code = .;
*(.text)
*(.rodata*)
. = ALIGN(4096);
}
.data . : AT(data)
{
data = .;
*(.data)
. = ALIGN(4096);
}
.bss . : AT(bss)
{
bss = .;
*(.bss)
. = ALIGN(4096);
}
end = .;
}
main.c:
#include <stdio.h>
#include <common.h>
#include <gdt.h>
int main() {
gdt_install();
puts("This is a minimal example...");
return 0;
}
common.c:
#include <common.h>
void *memcpy(void *dst, const void *src, size_t n) { return (void *)0; }
void *memset(void *dst, const char val, size_t n) { return (void *)0; }
void *memsetw(void *dst, const ushort val, size_t n) { return (void *)0; }
void *memseti(void *dst, const int val, size_t n) { return (void *)0; }
stdio.c:
#include <stdio.h>
#include <common.h>
ushort *screen_mem;
int colour = 0x0F;
int xpos = 0, ypos = 0;
int numcols = 80, numrows = 25;
void init_video() {}
size_t strlen(char *str) { return 0; }
void cls() { }
inline void scroll() { }
inline void newline() { }
void writech(char c) { }
void putch(char c) { }
void puts(char *str) { }
void set_text_colour(unsigned char f, unsigned char b){ }
gdt.c:
#include <gdt.h>
struct gdt_entry gdt[3];
struct gdt_ptr gdtp;
void gdt_set_gate(int n, ulong base, ulong limit, uchar access, uchar gran) { }
void gdt_install() { }
gdt.asm:
global gdt_reset
gdt_reset:
ret
gdt_reset2:
ret
включают в себя /common.h:
#ifndef __COMMON_H
#define __COMMON_H
typedef unsigned short ushort;
typedef unsigned char uchar;
typedef unsigned int uint;
typedef unsigned long ulong;
typedef int size_t;
void *memcpy(void *dst, const void *src, size_t n);
void *memset(void *dst, const char val, size_t n);
void *memsetw(void *dst, const ushort val, size_t n);
void *memseti(void *dst, const int val, size_t n);
#endif
включают в себя /stdio.h:
#ifndef __STDIO_H
#define __STDIO_H
#include <common.h>
void cls();
void writech(char c);
void putch(char c);
void puts(char *str);
void set_text_colour(uchar f, uchar b);
void init_video();
size_t strlen(char *str);
#endif
включают в себя /gdt.h:
#ifndef __GDT_H
#define __GDT_H
#include <common.h>
struct gdt_entry {
ushort limit_low;
ushort base_low;
uchar base_middle;
uchar access;
uchar granularity;
uchar base_high;
} __attribute__((packed));
struct gdt_ptr {
ushort limit;
uint base;
} __attribute__((packed));
void gdt_set_gate(int n, ulong base, ulong limit, uchar access, uchar gran);
void gdt_install();
extern void gdt_reset();
#endif
Вывод "objdump -t" в общую библиотеку, включающую все файлы .o(кроме kernel_loader, следовательно, символ undefined _start.
> i586-elf-objdump -t libos.so.1.0.1
libos.so.1.0.1: file format elf32-i386
SYMBOL TABLE:
08048080 l d .text 00000000 .text
08048162 l d .rodata 00000000 .rodata
08049180 l d .data 00000000 .data
0804918c l d .bss 00000000 .bss
00000000 l d .stab 00000000 .stab
00000000 l d .stabstr 00000000 .stabstr
00000000 l d .comment 00000000 .comment
00000000 l df *ABS* 00000000 main.c
00000000 l df *ABS* 00000000 stdio.c
00000000 l df *ABS* 00000000 common.c
00000000 l df *ABS* 00000000 gdt.c
00000000 l df *ABS* 00000000 gdt.asm
08048161 l .text 00000000 gdt_reset2
08049180 g O .data 00000004 colour
08048125 g F .text 00000014 memsetw
0804918c g O .bss 00000004 xpos
08049188 g O .data 00000004 numrows
08048158 g F .text 00000005 gdt_install
08048108 g F .text 0000000a memcpy
080480ee g F .text 00000005 puts
08049198 g O .bss 00000018 gdt
08049194 g O .bss 00000004 screen_mem
080480e0 g F .text 0000000e putch
08048144 g F .text 00000014 gdt_set_gate
00000000 *UND* 00000000 _start
08048160 g .text 00000000 gdt_reset
080480b4 g F .text 00000005 init_video
080480c8 g F .text 00000005 scroll
0804918c g *ABS* 00000000 __bss_start
08048112 g F .text 00000013 memset
08048080 g F .text 00000033 main
080480f3 g F .text 00000014 set_text_colour
080480cd g F .text 00000005 newline
08049190 g O .bss 00000004 ypos
080491b0 g O .bss 00000006 gdtp
0804918c g *ABS* 00000000 _edata
080491b8 g *ABS* 00000000 _end
080480c3 g F .text 00000005 cls
080480b9 g F .text 0000000a strlen
08048139 g F .text 0000000a memseti
08049184 g O .data 00000004 numcols
080480d2 g F .text 0000000e writech
Ответы
Ответ 1
Это звучит как проблема с круговой ссылкой на линии ссылки. Компилятор проходит через объектные файлы по порядку и "запоминает" любые нерешенные внешние. Однако он также может отбрасывать любые объектные файлы, которые не имеют ссылок на них. Если два или более объектных файла ссылаются друг на друга (вызывая циклическую ссылку), компоновщик может не отслеживать неразрешенные объекты.
Попробуйте дублировать части линии ссылок, а затем сузите их до нужных вам.
i586-elf-ld -T link.ld -o kernel32.bin kernel_loader.o main.o stdio.o common.o gdt.o gdt_asm.o \
stdio.o common.o gdt.o gdt_asm.o
Ответ 2
Порядок файлов в командной строке, по-видимому, имеет значение с помощью компоновщика GNU. Поместите файл .o
, содержащий точку входа (kernel_loader.o
), сначала в командной строке, затем любые объекты, которые он непосредственно ссылается, а затем объекты, на которые ссылаются эти объекты (и которые еще не находятся в CMD-линии) и т.д., или возможно, что компоновщик пропустит некоторые файлы.
Ответ 3
Есть другой вопрос SO (может быть похожим/идентичным, я не уверен), который охватывает некоторые из них. Помогает ли эта помощь?
Ответ 4
Я видел подобные проблемы несколько раз и в определенный момент, перед тем, как я начинаю безумно безумно, я начинаю искать невидимые вещи, которые могут оказаться в именах. Не-ASCII-байты или непечатаемые символы ASCII, которые могли проникнуть в ваш исходный код и привязаны к первому коду, увиденному после gdt_install();
Возможно, вам захочется добавить комментарий или пустой макрос (или do{}while(0)
) между вашим вызовом gdt_install()
и следующей реальной строкой кода. Возможно, даже доведите курсор до имени функции и верните ее до первого символа имени этой функции и начните вводить то, что вы решили добавить туда. Если это что-то, вызванное присутствием gdt_install();
, тогда что-то другое, забрасываемое туда, должно вызвать другую ошибку.
Если вы еще этого не сделали, вы можете просмотреть вывод препроцессора файла с вызовом gdt_install()
, а также его вывод сборки.
Если ничто из этого не вызывает ничего интересного, измените имя gdt_install
и посмотрите, не изменит ли это что-либо. Я видел несколько примеров, когда ошибки в компиляторе и/или компоновщике могут создавать нечто странное. Возможно, ошибка в хеш-таблице, используемой в качестве таблицы символов (возможно, даже в хэш-таблице файла эльфа).
Надеюсь, вы это поймете.
Ответ 5
какая-то дикая догадка, возможно, ваша функция ассемблера, которая называется (и, возможно, встроенная) в gdt_install
, испортила то, что происходит после нее. (этот прыжок в конце до ret
необычен, никогда не видел этого)
Является ли ваш gdt_install
в том же компиляционном блоке, где и у вас есть вызов? Используете ли вы -O[12]
для компиляции? Является ли вызов вложенным? Как выглядит ассемблер, создаваемый компилятором для стороны вызова?
Вы пытались скомпилировать с помощью -O0 -g
или -fno-inline
(или как этот параметр вызывается)?
Ответ 6
Ты написал. "I've implemented my own psuedo-stdio functions (puts, putch...) the functions match exactly ...
" Вы используете что-нибудь в стандартном libc? Если вы этого не сделаете, добавьте -nostdlib
в свою командную строку. Я видел странные вещи, когда я пытался переопределить функции в стандартном libc.
Ответ 7
Я подозреваю, что, возможно, объединение таблиц связующих символов из созданного объекта nasm и объектов, генерируемых gcc/gas, могло бы что-то испортить.
Не могли бы вы попытаться заменить вызов на gtd_install
вызовом короткой встроенной функции, содержащей встроенную сборку, которая вызывает или переходит на gtd_install
и находится в том же файле, что и текущий вызов gtd_install
?
Еще одна вещь, которая появилась у меня в голове, заключается в том, что если gtd_install
написано на ассемблере, то возможно, что она не будет на 100% синтаксически правильной. Я никогда не видел ничего подобного, но просто думал, что возможно, что границы gtd_install
(особенно конец) или его размер неправильно определены ассемблером, и это просто имеет случайные результаты.
Убедившись, что я думаю, что вам придется пойти к людям binutils и попросить их о помощи напрямую.