Chinaunix首页 | 论坛 | 博客
  • 博客访问: 51269
  • 博文数量: 8
  • 博客积分: 15
  • 博客等级: 民兵
  • 技术积分: 120
  • 用 户 组: 普通用户
  • 注册时间: 2010-03-04 20:32
个人简介

aaaaaaaaaaaaaaaaaaaa

文章分类

全部博文(8)

文章存档

2013年(8)

我的朋友

分类: Android平台

2013-09-07 10:58:17

今天在开发一个Android Native KAL层app的时候遇到一个问题,在Binder通信中,一不小心忘记了在

点击(此处)折叠或打开

  1. status_t BnXXXXXXXX::onTransact(
  2.             uint32_t code,
  3.             const Parcel& data,
  4.             Parcel* reply,
  5.             uint32_t flags)
  6. {
  7.     switch(code)
  8.     {
  9.         case XXXHAL_GET_MEMROY:
  10.         {
  11. //...
  12.             //I forgot next line,of course carelessly.
  13.            return NO_ERROR;
  14.            //...

结果在Binder Client端无法得到正确的结果,后来分析了一下原因,如果没返回值,按照arm-eabi-gcc 的规则,会直接将ARM中的r0丢给function 的caller,造成返回值的不确定性(这个道理跟定义一个没有initialized 的local variable原因一样),

如果返回不是NO_ERROR, Android会将返回的data写为Error Code以供Debug(所以Client端得不到正确的值),请看: IPCThreadState.cpp

点击(此处)折叠或打开

  1. status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,
  2.     int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer)



过反汇编即可看到,不过这支文件很大,不方便看,我用一个简单点的给大家解释一下。


1. 在下面这个native app中

点击(此处)折叠或打开

  1. static int getParameter()
  2. {
  3.     int index;
  4.     return 0x1234;
  5. }

  6. int main(int argc,char* argv[])
  7. {
  8.    int ret_value;
  9.    ret_value = getParameter();
  10.    terminal_print("ret: 0x%x",ret_value);

  11.     return 0;
  12. }
编译完后可以通过 objdump -dS SimpleTest.o > SimpleTest.o.txt 将assembly dump 成文件(assembly code跟source code对应,可以参考objdump的help
  -d, --disassemble        Display assembler contents of executable sections
  -D, --disassemble-all    Display assembler contents of all sections
  -S, --source             Intermix source code with disassembly

通过dump出来的assembly可以看到 r0将正确包含返回值:

点击(此处)折叠或打开

  1. static int getParameter()
  2. {
  3.    0:    e52db004     push    {fp}        ; (str fp, [sp, #-4]!)
  4.    4:    e28db000     add    fp, sp, #0
  5.     int index;
  6.     return 0x1234;
  7.    8:    e3a03c12     mov    r3, #4608    ; 0x1200
  8.    c:    e2833034     add    r3, r3, #52    ; 0x34
  9. }
  10.   10:    e1a00003     mov    r0, r3
  11.   14:    e28bd000     add    sp, fp, #0
  12.   18:    e8bd0800     ldmfd     {fp}
  13.   1c:    e12fff1e     bx    lr
2.  在上面的例子中,我们将return砍掉,然后,查看结果,返回不确定的值。
通过assembly ,可以看到,gcc直接将r3-->r0,然后返回,而r3的值是不确定的。

点击(此处)折叠或打开

  1. static int getParameter()
  2. {
  3.    0:    e52db004     push    {fp}        ; (str fp, [sp, #-4]!)
  4.    4:    e28db000     add    fp, sp, #0
  5.     int index;
  6. // return 0x1234;
  7. }
  8.    8:    e1a00003     mov    r0, r3
  9.    c:    e28bd000     add    sp, fp, #0
  10.   10:    e8bd0800     ldmfd     {fp}
  11.   14:    e12fff1e     bx    lr
一个简单的例子,Share给大家,另外自己学习了一下如何dump 跟source code match的assembly code.
关于这方面,参考的是:  

How to get gcc to interleave assembly output with original source code


 
另外还可以使用 ‘gcc -S -fverbose-asm test.c 的方法
写code一定要小心,不能带入任何一点不确定性。

出来混早晚要还的。


Ps. 使用 objdump -dS 的时候,要debug version的,我的native HAL 是Android NDK app, 目录在: lib\obj\local\armeabi\objs-debug\SimpleTest





阅读(2047) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~