How to inline a function from libc with gcc?

2019-08-13 01:19发布

问题:

I'm having the following problem: my software is causing a deadlock and the only clue that I have about its origin is a primitive stack trace with only 8 levels provided by my chipset for situations like this.

However, my stack trace is something like:

memset
memset
memset
memset
memset
memset
memset
memset

I want to remove memset out of my way to see which function is causing this mess. If I ask gcc to inline memset, it will complain stating that I don't have the function body for it.

So, is there a way to inline memset? Does anyone have any other idea about debugging this problem?

EDIT

I've already tried to replace memset with a dumb implementation using a for, but this made my software behave strangely and other problems appear that prevents me from getting to the deadlock.

EDIT

By the way, I'm using the MIPS arch. I'm not an MIPS assembly expert, so I've made a dumb attempt at getting the disassembled code for memset and inserting in the body of a C function. I got different instructions from objdump -d and gdb disassemble, so I've tried with both of them. Here are the functions that I've created:

void * memset(void * str_a, int ch, size_t count) {
    asm("mov    #12,r0");
    asm("cmp/gt r6,r0");
    asm("mov    r4,r0");
    asm("bt.s   30 <.L_dup_bytes+0x18>");
    asm("add    r4,r6");
    asm("tst    #3,r0");
    asm("bt.s   18 <.L_dup_bytes>");
    asm("extu.b r5,r5");
    asm("mov.b  r5,@r0");
    asm("add    #1,r0");
    asm("tst    #3,r0");
    asm("bf 10 <_memset+0x10>");
}

void * memset(void * str_a, int ch, size_t count) {
    asm("mov    #12,r0");
    asm("cmp/gt r6,r0");
    asm("mov    r4,r0");
    asm("bt.s   0x8163682c <memset+48>");
    asm("add    r4,r6");
    asm("tst    #3,r0");
    asm("bt.s   0x81636814 <memset+24>");
    asm("extu.b r5,r5");
    asm("mov.b  r5,@r0");
    asm("add    #1,r0");
    asm("tst    #3,r0");
    asm("bf 0x8163680c <memset+16>");
    asm("swap.b r5,r2");
    asm("or r2,r5");
    asm("swap.w r5,r2");
    asm("or r2,r5");
    asm("add    #-16,r6");
    asm("nop    ");
    asm("mov.l  r5,@r0");
    asm("cmp/hs r6,r0");
    asm("mov.l  r5,@(4,r0)");
    asm("bf.s   0x81636820 <memset+36>");
    asm("add    #8,r0");
    asm("add    #16,r6");
    asm("cmp/eq r6,r0");
    asm("bt 0x81636838 <memset+60>");
    asm("mov.b  r5,@r0");
    asm("add    #1,r0");
    asm("cmp/eq r6,r0");
    asm("bf 0x81636830 <memset+52>");
    asm("rts    ");
    asm("mov    r4,r0");
}

This gave me the following errors:

First memset:

/tmp/ccAuFFap.s: Assembler messages:
/tmp/ccAuFFap.s:3457: Warning: missing operand; zero assumed
/tmp/ccAuFFap.s:3469: Warning: missing operand; zero assumed
/tmp/ccAuFFap.s:3489: Warning: missing operand; zero assumed
/tmp/ccAuFFap.s:3457: Error: displacement to defined symbol .L0 overflows 8-bit field
/tmp/ccAuFFap.s:3469: Error: displacement to undefined symbol .L0 overflows 8-bit field 
/tmp/ccAuFFap.s:3489: Error: displacement to defined symbol .L0 overflows 8-bit field

Second memset:

/tmp/cctCDgi5.s: Assembler messages:
/tmp/cctCDgi5.s:3457: Warning: missing operand; zero assumed
/tmp/cctCDgi5.s:3469: Warning: missing operand; zero assumed
/tmp/cctCDgi5.s:3489: Warning: missing operand; zero assumed
/tmp/cctCDgi5.s:3529: Warning: missing operand; zero assumed
/tmp/cctCDgi5.s:3545: Warning: missing operand; zero assumed
/tmp/cctCDgi5.s:3561: Warning: missing operand; zero assumed
/tmp/cctCDgi5.s:3457: Error: displacement to defined symbol .L0 overflows 8-bit field
/tmp/cctCDgi5.s:3469: Error: displacement to defined symbol .L0 overflows 8-bit field
/tmp/cctCDgi5.s:3489: Error: displacement to defined symbol .L0 overflows 8-bit field
/tmp/cctCDgi5.s:3529: Error: displacement to defined symbol .L0 overflows 8-bit field
/tmp/cctCDgi5.s:3545: Error: displacement to defined symbol .L0 overflows 8-bit field
/tmp/cctCDgi5.s:3561: Error: displacement to defined symbol .L0 overflows 8-bit field

Can someone help with those errors?

EDIT

Tried another version with the source code from :

void * memset(void * str_a, int ch, size_t count) {    
    asm("slti    t1, a2, 8               ");
    asm("bne     t1, zero, L(last8)");
    asm("move    v0, a0                  ");
    asm("beq     a1, zero, L(ueven)      ");
    asm("andi    a1, 0xff                ");
    asm("sll     t0, a1, 8");
    asm("or      a1, t0");
    asm("sll     t0, a1, 16");
    asm("or      a1, t0                  ");
    asm("L(ueven):       ");
    asm("subu    t0, zero, a0            ");
    asm("andi    t0, 0x3");
    asm("beq     t0, zero, L(chkw)");
    asm("subu    a2, t0");
    asm("SWHI    a1, 0(a0)               ");
    asm("addu    a0, t0                  ");
    asm("L(chkw):        ");
    asm("andi    t0, a2, 0x7             ");
    asm("beq     t0, a2, L(chkl)");
    asm("subu    a3, a2, t0");
    asm("addu    a3, a0                  ");
    asm("move    a2, t0                  ");
    asm("L(loopw):       ");
    asm("addiu   a0, 8                   ");
    asm("sw      a1, -8(a0)");
    asm("bne     a0, a3, L(loopw)");
    asm("sw      a1, -4(a0)");
    asm("L(chkl):        ");
    asm("andi    t0, a2, 0x4             ");
    asm("beq     t0, zero, L(last8)      ");
    asm("subu    a2, t0");
    asm("sw      a1, 0(a0)               ");
    asm("addiu   a0, 4");
    asm("L(last8):       ");
    asm("blez    a2, L(exit)             ");
    asm("addu    a3, a2, a0              ");
    asm("L(lst8l):       ");
    asm("addiu   a0, 1");
    asm("bne     a0, a3, L(lst8l)");
    asm("sb      a1, -1(a0)");
    asm("L(exit):        ");
    asm("j       ra                      ");
    asm("nop");
}

Here are the errors this time:

/tmp/ccuyfGW5.s: Assembler messages:
/tmp/ccuyfGW5.s:5131: Error: unknown opcode
/tmp/ccuyfGW5.s:5135: Error: unknown opcode
/tmp/ccuyfGW5.s:5139: Error: unknown opcode
/tmp/ccuyfGW5.s:5143: Error: unknown opcode
/tmp/ccuyfGW5.s:5147: Error: unknown opcode
/tmp/ccuyfGW5.s:5151: Error: unknown opcode
/tmp/ccuyfGW5.s:5155: Error: invalid operands for opcode
/tmp/ccuyfGW5.s:5159: Error: unknown opcode
/tmp/ccuyfGW5.s:5163: Error: invalid operands for opcode
/tmp/ccuyfGW5.s:5167: Error: unknown opcode
/tmp/ccuyfGW5.s:5171: Error: unknown opcode
/tmp/ccuyfGW5.s:5175: Error: unknown opcode
/tmp/ccuyfGW5.s:5179: Error: unknown opcode
/tmp/ccuyfGW5.s:5183: Error: unknown opcode
/tmp/ccuyfGW5.s:5187: Error: unknown opcode
/tmp/ccuyfGW5.s:5191: Error: unknown opcode
/tmp/ccuyfGW5.s:5195: Error: unknown opcode
/tmp/ccuyfGW5.s:5199: Error: unknown opcode
/tmp/ccuyfGW5.s:5203: Error: unknown opcode
/tmp/ccuyfGW5.s:5207: Error: unknown opcode
/tmp/ccuyfGW5.s:5211: Error: unknown opcode
/tmp/ccuyfGW5.s:5215: Error: unknown opcode
/tmp/ccuyfGW5.s:5219: Error: unknown opcode
/tmp/ccuyfGW5.s:5223: Error: unknown opcode
/tmp/ccuyfGW5.s:5227: Error: unknown opcode
/tmp/ccuyfGW5.s:5231: Error: unknown opcode
/tmp/ccuyfGW5.s:5235: Error: unknown opcode
/tmp/ccuyfGW5.s:5239: Error: unknown opcode
/tmp/ccuyfGW5.s:5243: Error: unknown opcode
/tmp/ccuyfGW5.s:5247: Error: unknown opcode
/tmp/ccuyfGW5.s:5251: Error: unknown opcode
/tmp/ccuyfGW5.s:5255: Error: unknown opcode
/tmp/ccuyfGW5.s:5259: Error: unknown opcode
/tmp/ccuyfGW5.s:5263: Error: unknown opcode
/tmp/ccuyfGW5.s:5267: Error: unknown opcode
/tmp/ccuyfGW5.s:5271: Error: unknown opcode
/tmp/ccuyfGW5.s:5275: Error: unknown opcode
/tmp/ccuyfGW5.s:5279: Error: unknown opcode
/tmp/ccuyfGW5.s:5283: Error: unknown opcode
/tmp/ccuyfGW5.s:5287: Error: unknown opcode
/tmp/ccuyfGW5.s:5291: Error: unknown opcode
/tmp/ccuyfGW5.s:5295: Error: unknown opcode

EDIT

The problem was indeed related to stack corruption, but I'll let this question here to see if anyone knows the answer about how to get the disassembled code from a subroutine and put it back into a C function body for inlining.

回答1:

Neither gdb nor objdump produce code that the gcc inline MIPS assembler will accept. I'm not aware of any tool that automatically fixes the syntax, so manual correction of the assembler syntax will be needed. You would also need to tell gcc which registers and/or memory will get altered by the inline asm code. All of this is not a trivial task.

If you had C source code,the -S option of gcc produces almost syntactically correct MIPS assembler, but even that requires some manual editing.



标签: gcc inline mips