26

リンカ スクリプトの問題と思われる問題のトラブルシューティングを誰かが手伝ってくれることを願っています。

新しい関数への呼び出しを追加した後、奇妙な問題が発生しました。関数呼び出しがなければ、オブジェクト ファイルは正しくリンクされますが、新しい関数呼び出しを追加すると、別のオブジェクト ファイルからシンボルへの未定義の参照が取得されます (objdump を使用して実際に存在することを確認しました)。

また、奇妙なことに、関数呼び出しが存在する場合、最初に ld -r (再配置可能な出力を提供するため) を使用してすべてのオブジェクト ファイルをリンクし、次にリンク スクリプトを使用すると、未定義の参照はありませんが、リンク スクリプトは無視されているようです。出力バイナリに正しいエントリ ポイントがありません。

私の(クロスコンパイラ)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'

NB (この出力を作成したとき、nasm コンパイル済みアセンブラーに gdt.bin というファイル名を使用していましたが、実際には別の .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

私のリンクスクリプト(関連するかどうかはわかりません):

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 の putch への呼び出しをコメントアウトすると、代わりに 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() 呼び出しの上に移動すると、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() の上に移動すると、未定義の 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() の上で、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しかし、あまり運がありませんでした。

ありがとう

編集:

関連性があるかどうかはわかりませんが、リンク時にリンクスクリプトを省略すると、以前のエラーはすべて消えます... (ただし、エルフバイナリを理解しないため、ブートローダーはカーネルを呼び出すことができません)。

要求に応じて、前処理の前後の 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 を提案してより良い逆アセンブリ出力を提供してくれた nategoose に感謝します。

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

要求どおり、stdio.o での nm -s の出力は次のとおりです。

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継続的な関心と支援に感謝します。

メイクファイル:

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 $@

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 $@

kernel32.bin: $(ALL) $(INCLUDES)
    $(LD) $(LFLAGS) -o $@ -\( $(ALL) -\)

clean:
    rm -f $(ALL) kernel32.bin

リンク スクリプト:

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

すべての .o ファイルを含む共有ライブラリを「objdump -t」した場合の出力 (kernel_loader を除く、したがって未定義の _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
4

7 に答える 7

3

これは、リンク行での循環参照の問題のようです。リンカーはオブジェクト ファイルを順番に調べ、未解決の外部ファイルを「記憶」します。ただし、それらへの参照を持たないオブジェクト ファイルを破棄することもできます。2 つ以上のオブジェクト ファイルが相互に参照する (循環参照が発生する) 場合、リンカーは未解決のエンティティを追跡できない場合があります。

リンク行の一部を複製してみて、必要なものに絞り込んでください。

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
于 2010-07-19T14:19:39.267 に答える
2

コマンド ラインでのファイルの順序は、GNU リンカでは重要なようです。エントリ.oポイント ( ) を含むファイルをkernel_loader.o最初にコマンド ラインに配置し、次にそれが直接参照するオブジェクトを配置し、次にそれらのオブジェクトによって参照されるオブジェクト (まだコマンド ラインにない) などを配置します。リンカーがいくつかのファイルを見逃すこと。

于 2010-07-15T18:53:34.410 に答える
0

これのいくつかをカバーする別のSOの質問があります(類似/同一かもしれません、私にはわかりません)。それは何か助けを提供しますか?

于 2010-07-15T17:58:47.480 に答える
0

あなたが書いた。" I've implemented my own psuedo-stdio functions (puts, putch...) the functions match exactly ..." 標準の libc で何か使用していますか? そうでない場合は-nostdlib、コマンドラインに追加する必要があります。標準の libc で関数をオーバーライドしようとすると、奇妙なことが起こるのを見てきました。

于 2010-07-20T22:44:46.213 に答える
0

私は似たような問題を数回見たことがありますが、ある時点で、完全に狂ってしまう直前に、名前につながる可能性のある目に見えないものを探し始めました。ソースコードに忍び込み、その後に表示される最初のコードに添付された可能性のある非ASCIIバイトまたは印刷不可能なASCII文字gdt_install();

do{}while(0)への呼び出しgdt_install()と次の実際のコード行の間に、コメントまたは空のマクロ (または ) を追加してみてください。たぶん、カーソルを関数名に置き、その関数名の最初の文字の直前までカーソルを戻し、そこに追加することに決めたものを入力し始めることさえできます。それがの存在によって引き起こされたものである場合gdt_install();、そこに別の何かがスローされると、別のエラーが発生するはずです。

まだ行っていない場合は、への呼び出しを含むファイルのプリプロセッサ出力とgdt_install()そのアセンブリ出力を表示することをお勧めします。

どれも興味深いものを生み出さない場合は、 の名前を変更して、gdt_install何かが変わるかどうかを確認してください。コンパイラやリンカのバグがこのような奇妙なものを生成する可能性があるいくつかの例を見てきました。おそらく、シンボル テーブルとして使用されるハッシュ テーブルのバグです (おそらく、elf ファイルのハッシュ テーブルでも)。

これを理解してください。

于 2010-07-20T18:08:27.877 に答える
0

おそらく、nasm で生成されたオブジェクトと gcc/gas で生成されたオブジェクトからのリンク シンボル テーブルを組み合わせると、何かが台無しになるのではないかと思います。

への呼び出しを、への現在の呼び出しと同じファイルにgtd_install呼び出しまたはジャンプして常駐するインライン アセンブリを含む短いインライン関数への呼び出しに置き換えてみてください。gtd_installgtd_install

もう 1 つ思いついたのは、gtd_installがアセンブリ言語で記述されている場合、構文的に 100% 正しくない可能性があるということです。私はこのようなものを見たことがありませんが、gtd_installの境界 (特に最後) またはそのサイズがアセンブラーによって正しく決定されず、ランダムな結果が得られる可能性があると考えているだけです。

binutils の人のところに行って、直接助けを求めなければならないと思います。

于 2010-07-21T13:47:14.257 に答える
0

おそらく、呼び出された(そしておそらくインライン化された)アセンブラ関数が、gdt_installその後に来るものを台無しにしています。(この前の最後のジャンプretは珍しい、見たことがない)

あなたgdt_installが呼び出しを持っている場所と同じコンパイル ユニットにいますか? -O[12]コンパイルに使用しますか?呼び出しはインラインですか? 呼び出し側のためにコンパイラが生成するアセンブラはどのように見えますか?

-O0 -gor -fno-inline(またはこのオプションの呼び出し方法)を使用してコンパイルしようとしましたか?

于 2010-07-20T21:34:49.400 に答える