为ROM版芯片打patch

前言

国内大部分蓝牙芯片原厂的controller都是购买的IP(Intellectual Property),因为IP公司出售的controller代码已经十分稳定。所以会将controller做成ROM版,以降低成本。而芯片Tape out后难免会有一些BUG,这样ARM crotex M4 的code-patch ability for ROM system updates function 就有了用武之地!

技术路线

我们预先在lds文件中流出256Bytes 空间专门留给Host来打patch:

    .flashpatch (NOLOAD) :
    {
        KEEP(*(.flashpatch))
        . = 0x100;
        . = ALIGN(4);
    } > RAM

这样虽然蓝牙子系统是ROM版,不能重新烧写程序,但是我们可以在Host端编写patch,然后写到这片预留好的patch空间中。

这样每当执行错误代码段,就可以跳到patch空间执行正确代码,再跳回到到正常的代码。

于是出现了一个棘手的问题:

预留的patch空间有限,我们不可能将错误的代码块修改后反汇编成机器码,全部写入到patch空间中。因此patch的跳出地址和返回跳入地址的选择尤为关键!

打patch常用的汇编指令

**1. nop **

控制指令用来补齐

2. beq

beq指定是跳转指令,但是跳转要满足一定的条件,
例:
cmp        R1,#0    
beq        Label    
即当R1和0相等的时候程序跳到标号Label处执行  

cmp.w    sl, #4         f1ba 0f04
beq.n                   d001


beq.n 的计算:  从当前pc指针跳到下面指令 N行

那么 (N-4)   就是pc指针偏移量,
     (N-4) /2     就是指令后2位!

注:所以在打patch 的时候,我们可以先用beq.n 这种指令跳到patch 下面的位置,然后再跳出!

例:
a020011c:      f1ba 0f04    cmp.w   sl, #4
a0200120:       d002        beq.n   a0200128: <ld_clock_isr+0xdd6>
a0200122:       bf00    

        
跳出 1
a0200124:   0xba1cf607                      b. a0007560  
跳出 2
a0200128:   0xbd13f607                     b. a0007b52

3. b \ bl

B或BL指令引起处理器转移到“子程序名”处开始执行。
两者的不同之处在于BL指令在转移到子程序执行之前,将其下一条指令的地址拷贝到R14(LR,链接寄存器)。由于BL指令保存了下条指令的地址,因此使用指令“MOV PC ,LR”即可实现子程序的返回。
而B指令则无法实现子程序的返回,只能实现单纯的跳转。用户在编程的时候,可根据具体应用选用合适的子程序调用语句。

4. ldr

LDR指令的格式:
LDR{条件} 目的寄存器 <存储器地址>
作用:将 存储器地址 所指地址处连续的4个字节(1个字)的数据传送到目的寄存器中。

示例
a0200110: 4b06 ldr r3, [pc, #24]

LDR指令的寻址方式比较灵活,实例如下:
LDR R0,[R1]        ;将存储器地址为R1的字数据读入寄存器R0。
LDR R0,[R1,R2]    ;将存储器地址为R1+R2的字数据读入寄存器R0。
LDR R0,[R1,#8]         ;将存储器地址为R1+8的字数据读入寄存器R0。
LDR R0,[R1],R2       ;将存储器地址为R1的字数据读入寄存器R0,并将   R1+R2的值存入R1。
LDR R0,[R1],#8        ;将存储器地址为R1的字数据读入寄存器R0,并将R1+8的值存入R1。
LDR R0,[R1,R2]!      ;将存储器地址为R1+R2的字数据读入寄存器R0,并将R1+R2的值存入R1。
LDR R0,[R1,LSL #3]      ;将存储器地址为R1*8的字数据读入寄存器R0。
LDR R0,[R1,R2,LSL #2]  ;将存储器地址为R1+R2*4的字数据读入寄存器R0。
LDR R0,[R1,,R2,LSL #2]! ;将存储器地址为R1+R2*4的字数据读入寄存器R0,并将R1+R2*4的值存入R1。
LDR R0,[R1],R2,LSL #2  ;将存储器地址为R1的字数据读入寄存器R0,并将R1+R2*4的值存入R1。
LDR R0,Label           ;Label为程序标号,Label必须是当前指令的-4~4KB范围内。
 
要注意的是
LDR Rd,[Rn],#0x04     ;这里Rd不允许是R15。
 
另外LDRB 的指令格式与LDR相似,只不过它是将存储器地址中的8位(1个字节)读到目的寄存器中。
LDRH的指令格式也与LDR相似,它是将内存中的16位(半字)读到目的寄存器中。
 
LDR R0,=0xff
这里的LDR不是arm指令,而是伪指令。这个时候与MOVE很相似,只不过MOV指令后的立即数是有限制的。
这个立即数必须是0X00-OXFF范围内的数经过偶数次右移得到的数,所以MOV用起来比较麻烦,因为有些数不那么容易看出来是否合法。

5. pop

POP <reglist> t
a0023b18: bd38 pop {r3, r4, r5, pc}

我打个一个patch

先看一下c代码,在原本的if语句中添加了2个限制条件

if  ((((llc_env[conhdl]->chnl_assess_interfere_cnt[chnl])*100)>
    (llm_get_chnl_assess_interfere_per_thres_bad()*
    (llc_env[conhdl]->chnl_assess_pkt_cnt[chnl]))) &&
    (llm_util_check_map_validity(&llc_env[conhdl]->n_ch_map.map[0], 
    LE_CHNL_MAP_LEN)>2)&&
    //patch需要加入的2个限制条件
    (llc_env[conhdl]->role == ROLE_MASTER)&&
    (ke_state_get(dest_id) == LLC_MAP_UPD_WAIT_INSTANT))
  1. 反汇编
    将elf文件反汇编成asm文件

arm-none-eabi-objdump -S fw.elf >>fw.asm

  1. 选择跳出地址
    根据前一个patch计算当前patch的的首地址
0xa0038b74 -->   0xc000672c    跳转指令0xbddaf1cd    
//0xc00066c8+23*4+8 = 0xc000672c  
0xc000672c 和 0xa020672c 是同一个位置,但是b 跳转的时候不能跳太远,所以要跳到  0xa020672c 

a0038b72:   2802        cmp r0, #2
a0038b74:   d924        bls.n   a0038bc0 <lld_data_ind_handler+0x290>
入口地址必须是4字节对齐的(以0 4 8 c结尾的地址),所以我选择
a0038b74 作为入口,跳到patch 的ram 地址 0xc000672c;
然而我们实际跳转的bl指令跳不了很远,所以先调到0xa020672c,再跳到0xc000672c。
  1. 汇编指令的计算
0xc000672c :d90c            bls.n       0xc0006748  // a0038bc0
0xc000672e :bf00            nop
bls(Branch if Lower or the Same),指令的意思是如果(cmp   r0, #2)
判断结果是小于等于:那么就跳 0c 这个偏移(跳到0xa0206748,再从 0xa0206748,跳回原来的代码),
否则继续往下一条走。这个偏移的计算如下:(0xc0006748 - 0xc000672c - 4)/2 =0x0c 

解释:2个内存地址的偏移再 - 4,是因为arm 的流水线机制,取指令和执行指令的间隔是4个机器周期,
而这种跳转的指令都是2字节对齐,所以除以2。
     
0xc0006730: f859 3025   ldr.w   r3, [r9, r5, lsl #2]
0xc0006734: f893 30c5   ldrb.w  r3, [r3, #197]  ; 0xc5

0xc0006738:     b933        cbnz r3      0xa0206748  
0xc000673a: 9806         ldr     r0, [sp, #24]
解释:CBNZ (Compare and Branch on Non-Zero and Compare 
and Branch on Zero compares the value in a register with zero,
and conditionally branches forward a constant value. They do not affect the condition flags.)
跳转目标必须在指令之后的 4 到 130 个字节之内。
等同于:         CMP     Rn, #0
                BNE     label
0xc000673c: f5fa fd5a       bl  a00011f4 <ke_state_get>  

0xc0006740: 2805        cmp r0, #5
0xc0006742: d001        beq.n    0xa0206748 
beq:(如果之前比较相等就执行 beq指令,如果不等继续执行吓一条)
所以代码的意思是:r0=5,那么跳到  0xa0206748 ,否则跳到0xc0006744


0xc0006744:    0xf632 ba17         //a0038b76
0xc0006748:  -->  0xf632 ba3a   //0xa0038bc0   
  1. 最后生成patch 机器码
const uint32_t verd_patch7_ins_data[]  =
{   
    0xbf00d90c, 
    0x3025f859,
    0x30c5f893, 
    0x9806b933,
    0xfd5af5fa,
    0xd0012805,
    0xba17f632,
    0xba3af632 
};
const BTDRV_PATCH_STRUCT verd_ins_patch7 =
{
    7,
    BTDRV_PATCH_ACT,
    sizeof(verd_patch7_ins_data),
    0x00038b74,
    0xbddaf1cd,
    0xc000672c,
    (uint8_t *)verd_patch7_ins_data
};

2017年8月22日23:01:03

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容

  • 8086汇编 本笔记是笔者观看小甲鱼老师(鱼C论坛)《零基础入门学习汇编语言》系列视频的笔记,在此感谢他和像他一样...
    Gibbs基阅读 36,357评论 8 113
  • 王爽汇编全书知识点大纲 第一章 基础知识 机器语言 汇编语言的产生 汇编语言的组成 存储器 cpu对存储器的读写 ...
    2c3ba901516f阅读 2,341评论 0 1
  • 前言 本文翻译自iOS Assembly Tutorial: Understanding ARM 翻译的不对的地...
    桃红宿雨阅读 17,892评论 7 198
  • 一天晚上,我睡梦中忽然听到一个声音: “姐姐,姐姐” 我起身四望,并没有人,又躺下来。 “姐姐,姐姐” 这一次,我...
    sarah在行动阅读 582评论 2 3
  • ――你有你的好,我也有我的好 学心理学几年,最大的收获是把自己基本理顺了。心里纠结的时候少了,纠结时间短...
    箫音声声阅读 171评论 0 0