【发布时间】:2017-04-23 09:40:14
【问题描述】:
我正在使用 Samba 3.6.25 进行项目。 当我按照“smbclient”的源代码尝试构建自己的SMB服务器列表实用程序时,我遇到了一件奇怪的事情:
当我调用一个函数时,它跳过了我的第一个参数并用第二个参数填充它,然后第二个填充第三个,依此类推。
我调用的函数是:cli_pipe.c中的cli_rpc_pipe_open_noauth_transport()。我在其中添加了一些调试代码:
NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli,
enum dcerpc_transport_t transport,
const struct ndr_syntax_id *interface,
struct rpc_pipe_client **presult)
{
struct rpc_pipe_client *result;
struct pipe_auth_data *auth;
NTSTATUS status;
status = cli_rpc_pipe_open(cli, transport, interface, &result);
_DEBUG("cli = %p", cli);
_DEBUG("transport = %p", transport);
_DEBUG("interface = %p", interface);
_DEBUG("presult = %p", presult);
_DEBUG("cli->desthost = %p", cli->desthost);
_DEBUG("cli->desthost = \"%s\"", cli->desthost);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
……
这就是我调用这个函数的方式:
NTSTATUS _pipe_open_noauth(struct cli_state *cli, const struct ndr_syntax_id *intf, struct rpc_pipe_client **presult)
{
SMBD_DEBUG("cli = %p", cli);
SMBD_DEBUG("intf = %p", intf);
SMBD_DEBUG("presult = %p", presult);
SMBD_DEBUG("cli->desthost = %p", cli->desthost);
SMBD_DEBUG("cli->desthost = \"%s\"", cli->desthost);
return cli_rpc_pipe_open_noauth_transport(cli, 1, intf, presult);
}
这是我在控制台中得到的:
--- SMBD (util_smbclient.c, 117): cli = 0xdb2b20
--- SMBD (util_smbclient.c, 118): intf = 0xda31c0
--- SMBD (util_smbclient.c, 119): presult = 0x7fe9fdc8
--- SMBD (util_smbclient.c, 120): cli->desthost = 0xdd3a50
--- SMBD (util_smbclient.c, 121): cli->desthost = "192.168.1.125"
=== Samba (rpc_client/cli_pipe.c, 2873): cli = 0x1
=== Samba (rpc_client/cli_pipe.c, 2874): transport = 0xda31c0
=== Samba (rpc_client/cli_pipe.c, 2875): interface = 0x7fe9fdc8
=== Samba (rpc_client/cli_pipe.c, 2876): presult = 0xdaf3d0
这没有意义!注意到我传递的四个参数是: 0xdb2b20、0x1、0xda31c0、0x7fe9fdc8 但是 cli_rpc_pipe_open_noauth_transport() 得到的是: 0x1, 0xda31c0, 0x7fe9fdc8, 0xdaf3d0
很明显,第一个参数“0xdb2b20”丢失了,第二个参数取而代之。
有谁知道发生了什么,我该如何解决?
非常感谢您!
—— 附加信息:
我使用的工具链是 mipsel-linux-uclibc-cc/ld/ar。我试图 objdump 几个目标文件,看看发生了什么。
我转储了我自己的程序,这里是调用该函数的程序集。 注意到四个参数是按顺序传递的:a0、a1、a2、a3:
409bf0: 8fdc0010 lw gp,16(s8)
409bf4: 8fc40020 lw a0,32(s8)
409bf8: 24050001 li a1,1 # store “1” in a1
409bfc: 8fc60024 lw a2,36(s8)
409c00: 8fc70028 lw a3,40(s8)
409c04: 8f99ab74 lw t9,-21644(gp)
409c08: 00000000 nop
409c0c: 0320f809 jalr t9
409c10: 00000000 nop
409c14: 8fdc0010 lw gp,16(s8)
409c18: 03c0e821 move sp,s8
409c1c: 8fbf001c lw ra,28(sp)
409c20: 8fbe0018 lw s8,24(sp)
409c24: 03e00008 jr ra
409c28: 27bd0020 addiu sp,sp,32
然后我转储了 smbclient,它也调用了 cli_rpc_pipe_open_noauth_transport()。 问题来了:好像a0不是用来传参数的!!!
<cli_rpc_pipe_open_noauth>:
…
487840: 8fdc0018 lw gp,24(s8)
487844: 8fc2003c lw v0,60(s8)
487848: 00000000 nop
48784c: afa20010 sw v0,16(sp)
487850: 02002021 move a0,s0
487854: 8fc50034 lw a1,52(s8)
487858: 24060001 li a2,1 # Here, the number “1” was stored in a2 instead of a1!!!
48785c: 8fc70038 lw a3,56(s8)
487860: 8f99aed0 lw t9,-20784(gp)
487864: 00000000 nop
487868: 0320f809 jalr t9 # cli_rpc_pipe_open_noauth_transport()
48786c: 00000000 nop
487870: 8fdc0018 lw gp,24(s8)
487874: 02001021 move v0,s0
487878: 03c0e821 move sp,s8
48787c: 8fbf0028 lw ra,40(sp)
487880: 8fbe0024 lw s8,36(sp)
487884: 8fb00020 lw s0,32(sp)
487888: 03e00008 jr ra
48788c: 27bd0030 addiu sp,sp,48
最后我转储 cli_rpc_pipe_open_noauth_transport() 本身,似乎它以 smbclient 的方式工作:
0053bdac <cli_rpc_pipe_open_noauth_transport>:
53bdac: 3c1c0087 lui gp,0x87
53bdb0: 279c3624 addiu gp,gp,13860
53bdb4: 0399e021 addu gp,gp,t9
53bdb8: 27bdffc0 addiu sp,sp,-64
53bdbc: afbf0038 sw ra,56(sp)
53bdc0: afbe0034 sw s8,52(sp)
53bdc4: afb00030 sw s0,48(sp)
53bdc8: 03a0f021 move s8,sp
53bdcc: afbc0018 sw gp,24(sp)
53bdd0: afc40040 sw a0,64(s8)
53bdd4: afc50044 sw a1,68(s8)
53bdd8: afc60048 sw a2,72(s8)
53bddc: afc7004c sw a3,76(s8)
53bde0: 8f848080 lw a0,-32640(gp)
53bde4: 00000000 nop
53bde8: 24844da0 addiu a0,a0,19872
53bdec: 24050b39 li a1,2873
53bdf0: 8fc60044 lw a2,68(s8)
53bdf4: 8f99cab0 lw t9,-13648(gp)
53bdf8: 00000000 nop
53bdfc: 0320f809 jalr t9 <—— invoke cli_rpc_pipe_open()
53be00: 00000000 nop
附加信息 No.2 -- 我如何编译我的程序
- 我从官方 FTP 服务器下载了 Samba。
- 配置和制作(交叉编译)
- 在“source3”目录中找到所有 .o 文件,然后将它们全部归档到一个 .a 文件中。
- 创建我自己的应用程序,调用 Samba 函数,就像它自己的程序“smbclient”一样,有许多 -I 选项确保编译正常
- 链接 Samba 官方提供的 libsmbclient.a 和我自己在步骤 3 中归档的 .a。
附加信息3号
【问题讨论】:
-
确实看起来像一个编译器错误。如果减少测试用例,错误会消失吗?下一步可能是向构建工具链的人提出错误。除非您准备通过 gcc 进行跟踪 :)
-
你应该把你的 _DEBUG 放在 cli_rpc_pipe_open() 上面,以便在函数调用之前显示堆栈。
-
@Holger 我已将 _DEBUG 放在 cli_rpc_pipe_open() 之上,该函数也出现了同样的错误。我把它放在后面只是为了让我更容易定位参数传递(否则会有很多令人困惑的“jalr”指令)
-
@JonChesterfield 感谢您的评论。但是我想知道您所说的“减少测试用例”是什么意思?你是说那些 _DEBUG 指令吗?起初,我没有 _DEBUG,但出现“段错误”错误。因此我添加了很多 _DEBUG 试图定位哪里出了问题。
-
在调用约定方面似乎存在分歧
标签: c function assembly parameter-passing mips