Ps2toolchain: ELF 文件的最后一个字节有时会损坏

创建于 2020-01-15  ·  9评论  ·  资料来源: ps2dev/ps2toolchain

以下代码将产生无效输出:

#include <stdio.h>

extern const int i1, i2, i3, i4;

int main()
{
        printf("i1=%d\n", i1);
        printf("i2=%d\n", i2);
        printf("i3=%d\n", i3);
        printf("i4=%d\n", i4);

        return 0;
}

const int dum1=1;
const int dum2=2;
const int dum3=3;
//const int dum4=4;
//const int dum5=5;
//const int dum6=6;
const int i1=1111;
const int i2=2222;
const int i3=3333;
const int i4=4444;

当尝试使用随机数量的虚拟常数时,结果会有所不同:
好的:

i1=1111
i2=2222
i3=3333
i4=4444

糟糕:

i1=1111
i2=2222
i3=3333
i4=0
i1=1111
i2=2222
i3=0
i4=0



md5-a7a998816ff6355b19ebaf6bb16f20b1



i1=1111
i2=0
i3=0
i4=0



md5-50fa41c3352404f2cadd42c17104c34f



ee-gcc -o hello.elf hello.c
ps2client -h 192.168.1.10 execee host:hello.elf

此错误导致 OPL 中的 size_ds34bt_irx 和/或 size_ds34usb_irx 为 0。导致 OPL 在启动时随机崩溃(黑屏)。 在 OPL 中的任意位置添加一行代码会导致此错误出现和消失。

当使用以下命令查看时,无效值似乎在 ELF 文件的最后 128 位中:
ee-objdump -D hello.elf

elf 文件中的值很好,所以在加载 elf 时似乎在某处出错。

最有用的评论

我发现了错误:

crt0 清除 .bss 部分,以 16 字节/128 位为单位。 它要求 .bss 部分至少与 16 字节/128 位对齐。 以前,这是由 ps2sdk 中的链接器文件保证的。 但是,binutils 中的默认链接器脚本(我在此处添加:https://github.com/ps2dev/ps2toolchain/commit/7c494f217d379639aaca23d3c588e48986177a51)没有为 crt0 正确对齐 .bss 部分。 导致 .sdata 中的最后几个值也被清除。

我在这里为内置的 binutils 链接器脚本创建了一个修复程序。 它将成为 newlib PR 的一部分。

所有9条评论

你是如何得出这个结论的

如果 ELF 中的值看起来不错,您为什么不认为这是 ps2link 问题? 如果您使用其他方法加载 ELF 会怎样?
我认为这可能是由于 ps2link 没有清除内存造成的。 sceSifLoadElf() 函数不会将任何内存归零,因此如果在使用该函数加载 ELF 之前未擦除内存,则可能会出现错误数据。

如果 ELF 中的值看起来不错,您为什么不认为这是 ps2link 问题? 如果您使用其他方法加载 ELF 会怎样?

是的,ELF 文件中的数据看起来不错,所以我猜这个问题的标题有点误导。 我会尝试另一个装载机。

我认为这可能是由于 ps2link 没有清除内存造成的。 sceSifLoadElf() 函数不会将任何内存归零,因此如果在使用该函数加载 ELF 之前未擦除内存,则可能会出现错误数据。

const int 位于 .sdata(静态数据)部分。 我认为 .sdata 部分是以 16bytes/128bits 为单位从 elf 文件复制到内存中的。 也许如果 .sdata 部分不是 128 位的倍数,则不会复制剩余的数据,而是在其位置上留下零?
或者也许 .sdata 部分被正确复制,但另一个归零部分没有正确对齐它旁边? 并且在复制 .sdata 之后发生归零?

你好,
为了查看@sp193是否正确并且问题出在ps2link中,我修改了示例,现在它使用函数scr_prinf来查看屏幕中的输出并通过以下方式轻松执行ULaunchELF或加载到PCSX2

文件内容

#include <stdio.h>

void init_scr(void);
void scr_printf(const char *, ...) __attribute__((format(printf,1,2)));

extern const int i1, i2, i3, i4;

int main()
{
   init_scr();
   scr_printf("i1=%d\n", i1);
   scr_printf("i2=%d\n", i2);
   scr_printf("i3=%d\n", i3);
   scr_printf("i4=%d\n", i4);

   while(1) {}

   return 0;
}

const int dum1=1;
const int dum2=2;
const int dum3=3;
const int dum4=4;
const int dum5=5;
const int i1=1111;
const int i2=2222;
const int i3=3333;
const int i4=4444;

编译过程

ee-gcc -o hello.elf hello.c -L$PS2SDK/ee/lib -ldebug

在这种情况下,输出使用PCSX2
Screenshot 2020-01-15 at 09 47 54

如您所见,结果与@rickgaiser评论的结果相同。

i1=1111
i2=2222
i3=3333
i4=0

谢谢

ps2link 使用函数 SifLoadElf 加载 elf 文件:
https://github.com/ps2dev/ps2link/blob/1ec566c54bb8b567ee0a702982b392f37807b5e2/ee/cmdHandler.c#L138

来自ps2sdk:
https://github.com/ps2dev/ps2sdk/blob/5385a6ccd9db8c9fa54ecfd8af45322a5908bf6d/ee/kernel/src/loadfile.c#L129

这最终会在 IOP 上调用 RPC 函数。 加载文件的一部分。

这可能是 LOADFILE 中的错误吗? 或者也许我们的工具链没有按照 LOADFILE 期望的方式对齐这些部分? sbv_patches 可以解决这个问题吗? 我可以看到他们修补了 LOADFILE,但他们修补了与此相关的任何内容吗?

LOADFILE 的 SBV 补丁是为了启用 LoadModuleBuffer() 的 RPC 函数。 由于某种原因,LOADFILE 的早期版本不支持该功能。 索尼也对其进行了修补,因此显然它被忽略了。

我发现了错误:

crt0 清除 .bss 部分,以 16 字节/128 位为单位。 它要求 .bss 部分至少与 16 字节/128 位对齐。 以前,这是由 ps2sdk 中的链接器文件保证的。 但是,binutils 中的默认链接器脚本(我在此处添加:https://github.com/ps2dev/ps2toolchain/commit/7c494f217d379639aaca23d3c588e48986177a51)没有为 crt0 正确对齐 .bss 部分。 导致 .sdata 中的最后几个值也被清除。

我在这里为内置的 binutils 链接器脚本创建了一个修复程序。 它将成为 newlib PR 的一部分。

IIRC,您总是希望确保部分对齐 128 位。我相信这与 DMA 对齐或类似但不确定。

此问题已通过最近合并的 newlib PR 解决,特别是此提交: https ://github.com/ps2dev/ps2toolchain/commit/f5544b8d68fbdf611e277e9583714ae6627f3a61

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

lptech1024 picture lptech1024  ·  4评论

SignalSpectre picture SignalSpectre  ·  8评论

terremoth picture terremoth  ·  8评论

meleyal picture meleyal  ·  85评论

devlins picture devlins  ·  21评论