[Crash-utility] Problem with disassembling functions that use BUG()

Gerard Snitselaar snits at snitselaar.org
Mon Mar 6 18:25:26 UTC 2006


Using an AS4 i386 based system with a 2.6.9-22ELsmp kernel. Currently BUG()
gets defined as the following:

#define BUG()                           \
 __asm__ __volatile__(  "ud2\n"         \
                        "\t.word %c0\n" \
                        "\t.long %c1\n" \
                         : : "i" (__LINE__), "i" (__FILE__))


So after the ud2 opcode it places __LINE__ and __FILE__ in the next 6 bytes.
The trap handler for ud2 uses these to print a message saying where BUG() was 
used.

Crash has no knowledge of this convention so it thinks the byte after the ud2
opcode is the start of the next instruction. This results in bad disassemblies 
being generated. The example where I ran into it was flush_tlb_others() . 

Below I have included the source for flush_tlb_others , the disassembly from 
crash, the raw code for flush_tlb_others, and what I think the disassembly 
should be if one takes into account the convention used in BUG(). What 
initially made me suspicous was that I didn't see "call <_spin_lock>" 
anywhere, and the offsets for jumps didn't line up with instructions. From 
what I can tell this would probably have to be dealt with in print_insn() in 
gdb/opcodes/i386-dis.c . Not sure how to go about it, or what should be done 
since newer kernels allow you to configure whether those bytes get encoded 
after the ud2 opcode with CONFIG_DEBUG_VERBOSE.

Any ideas on solving this? 

source for flush_tlb_others:

static void flush_tlb_others(cpumask_t cpumask, struct mm_struct *mm,
                                                unsigned long va)
{
        cpumask_t tmp;
        /*
         * A couple of (to be removed) sanity checks:
         *
         * - we do not send IPIs to not-yet booted CPUs.
         * - current CPU must not be in mask
         * - mask must exist :)
         */
        BUG_ON(cpus_empty(cpumask));

        cpus_and(tmp, cpumask, cpu_online_map);
        BUG_ON(!cpus_equal(cpumask, tmp));
        BUG_ON(cpu_isset(smp_processor_id(), cpumask));
        BUG_ON(!mm);

        /*
         * i'm not happy about this global shared spinlock in the
         * MM hot path, but we'll see how contended it is.
         * Temporarily this turns IRQs off, so that lockups are
         * detected by the NMI watchdog.
         */
        spin_lock(&tlbstate_lock);
        
        flush_mm = mm;
        flush_va = va;
#if NR_CPUS <= BITS_PER_LONG
        atomic_set_mask(cpumask, &flush_cpumask);
#else
        {
                int k;
                unsigned long *flush_mask = (unsigned long *)&flush_cpumask;
                unsigned long *cpu_mask = (unsigned long *)&cpumask;
                for (k = 0; k < BITS_TO_LONGS(NR_CPUS); ++k)
                        atomic_set_mask(cpu_mask[k], &flush_mask[k]);
        }
#endif
        /*
         * We have to send the IPI only to
         * CPUs affected.
         */
        send_IPI_mask(cpumask, INVALIDATE_TLB_VECTOR);

        while (!cpus_empty(flush_cpumask))
                /* nothing. lockup detection does not belong here */
                mb();

        flush_mm = NULL;
        flush_va = 0;
        spin_unlock(&tlbstate_lock);
}

========

crash disassembly of flush_tlb_others:

crash> dis flush_tlb_others
0xc011681a <flush_tlb_others>:  push   %esi
0xc011681b <flush_tlb_others+0x1>:      test   %eax,%eax
0xc011681d <flush_tlb_others+0x3>:      push   %ebx
0xc011681e <flush_tlb_others+0x4>:      mov    %edx,%ebx
0xc0116820 <flush_tlb_others+0x6>:      mov    %eax,%edx
0xc0116822 <flush_tlb_others+0x8>:      push   %esi
0xc0116823 <flush_tlb_others+0x9>:      mov    %ecx,%esi
0xc0116825 <flush_tlb_others+0xb>:      mov    %eax,(%esp)
0xc0116828 <flush_tlb_others+0xe>:      jne    0xc0116832 
<flush_tlb_others+0x18>
0xc011682a <flush_tlb_others+0x10>:     ud2a
0xc011682c <flush_tlb_others+0x12>:     add    %sp,(%esi)
0xc011682f <flush_tlb_others+0x15>:     add    (%esi),%ebp
0xc0116831 <flush_tlb_others+0x17>:     rorb   $0x91,0x880523d0(%ecx)
0xc0116838 <flush_tlb_others+0x1e>:     inc    %eax
0xc0116839 <flush_tlb_others+0x1f>:     sarb   $0xc2,(%ecx)
0xc011683c <flush_tlb_others+0x22>:     je     0xc0116846 
<flush_tlb_others+0x2c>
0xc011683e <flush_tlb_others+0x24>:     ud2a
0xc0116840 <flush_tlb_others+0x26>:     imul   $0xc02e0326,(%ecx),%eax
0xc0116846 <flush_tlb_others+0x2c>:     mov    $0xfffff000,%eax
0xc011684b <flush_tlb_others+0x31>:     and    %esp,%eax
0xc011684d <flush_tlb_others+0x33>:     mov    0x10(%eax),%eax
0xc0116850 <flush_tlb_others+0x36>:     bt     %eax,(%esp)
0xc0116854 <flush_tlb_others+0x3a>:     sbb    %eax,%eax
0xc0116856 <flush_tlb_others+0x3c>:     test   %eax,%eax
0xc0116858 <flush_tlb_others+0x3e>:     je     0xc0116862 
<flush_tlb_others+0x48>
0xc011685a <flush_tlb_others+0x40>:     ud2a
0xc011685c <flush_tlb_others+0x42>:     push   $0x1
0xc011685e <flush_tlb_others+0x44>:     add    %es:(%esi),%ebp
0xc0116861 <flush_tlb_others+0x47>:     rolb   $0xb,0xf0875db(%ebp)
0xc0116868 <flush_tlb_others+0x4e>:     imul   $0x26,(%ecx),%eax
0xc011686b <flush_tlb_others+0x51>:     add    (%esi),%ebp
0xc011686d <flush_tlb_others+0x53>:     sarb   $0xe8,0xc0321c3c(%eax)
0xc0116874 <flush_tlb_others+0x5a>:     int    $0x93
0xc0116876 <flush_tlb_others+0x5c>:     sbb    (%eax),%eax
0xc0116878 <flush_tlb_others+0x5e>:     mov    %ebx,0xc0409160
0xc011687e <flush_tlb_others+0x64>:     mov    (%esp),%eax
0xc0116881 <flush_tlb_others+0x67>:     mov    %esi,0xc0409164
0xc0116887 <flush_tlb_others+0x6d>:     lock or %eax,0xc040915c
0xc011688e <flush_tlb_others+0x74>:     mov    0xc031f300,%ecx
0xc0116894 <flush_tlb_others+0x7a>:     mov    $0xfd,%edx
0xc0116899 <flush_tlb_others+0x7f>:     mov    (%esp),%eax
0xc011689c <flush_tlb_others+0x82>:     call   *0x80(%ecx)
0xc01168a2 <flush_tlb_others+0x88>:
    jmp    0xc01168aa <flush_tlb_others+0x90>
0xc01168a4 <flush_tlb_others+0x8a>:     mfence
0xc01168a7 <flush_tlb_others+0x8d>:     lea    0x0(%esi),%esi
0xc01168aa <flush_tlb_others+0x90>:     cmpl   $0x0,0xc040915c
0xc01168b1 <flush_tlb_others+0x97>:
    jne    0xc01168a4 <flush_tlb_others+0x8a>
0xc01168b3 <flush_tlb_others+0x99>:     movl   $0x0,0xc0409160
0xc01168bd <flush_tlb_others+0xa3>:     mov    $0xc0321c3c,%eax
0xc01168c2 <flush_tlb_others+0xa8>:     movl   $0x0,0xc0409164
0xc01168cc <flush_tlb_others+0xb2>:     call   0xc02cfcb6 <_spin_unlock>
0xc01168d1 <flush_tlb_others+0xb7>:     pop    %ebx
0xc01168d2 <flush_tlb_others+0xb8>:     pop    %ebx
0xc01168d3 <flush_tlb_others+0xb9>:     pop    %esi
0xc01168d4 <flush_tlb_others+0xba>:     ret

========

raw code for flush_tlb_others:

crash> rd flush_tlb_others 0x2f
c011681a:  53c08556 c289d389 89ce8956 08752404   V..S....V....$u.
c011682a:  01660b0f c02e0326 0523d089 c0409188   ..f.&.....#... at .
c011683a:  0874c239 01690b0f c02e0326 fff000b8   9.t...i.&.......
c011684a:  8be021ff a30f1040 c0192404 0874c085   .!.. at ....$....t.
c011685a:  016a0b0f c02e0326 0875db85 016b0b0f   ..j.&.....u...k.
c011686a:  c02e0326 321c3cb8 93cde8c0 1d89001b   &....<.2........
c011687a:  c0409160 8924048b 40916435 0509f0c0   `. at ...$.5d. at ....
c011688a:  c040915c f3000d8b fdbac031 8b000000   \. at .....1.......
c011689a:  91ff2404 00000080 ae0f06eb 00768df0   .$............v.
c01168aa:  915c3d83 7500c040 6005c7f1 00c04091   .=\. at ..u...`. at ..
c01168ba:  b8000000 c0321c3c 916405c7 0000c040   ....<.2...d. at ...
c01168ca:  e5e80000 5b001b93 52c35e5b            .......[[^.R

========

hand disassembly of flush_tlb_others taking into account
kernel convention of encoding __LINE__ and __FILE__ after
the ud2a opcode:

flush_tlb_others+0x000: 56               push %esi;
flush_tlb_others+0x001: 85c0             test %eax, %eax;
flush_tlb_others+0x003: 53               push %ebx;
flush_tlb_others+0x004: 89d3             mov %edx, %ebx;
flush_tlb_others+0x006: 89c2             mov %eax, %edx;
flush_tlb_others+0x008: 56               push %esi;
flush_tlb_others+0x009: 89ce             mov %ecx, %esi;
flush_tlb_others+0x00b: 890424           mov %eax, (%esp);
flush_tlb_others+0x00e: 7508             jne flush_tlb_others+0x18
flush_tlb_others+0x010: 0f0b             ud2;
flush_tlb_others+0x012: 660126032ec0     ; put __LINE__ __FILE__ here for trap 
handler
                                                  358   arch/i386/kernel/smp.c
flush_tlb_others+0x018: 89d0             mov %edx, %eax;
flush_tlb_others+0x01a: 2305889140c0     and 0xc0409188, %eax;
flush_tlb_others+0x020: 39c2             cmp %eax, %edx;
flush_tlb_others+0x022: 7408             je flush_tlb_others+0x2c
flush_tlb_others+0x024: 0f0b             ud2;
flush_tlb_others+0x026: 690126032ec0     ; put __LINE__ __FILE__ here for trap 
handler
                                                 361    arch/i386/kernel/smp.c 
flush_tlb_others+0x02c: b8000fffff       mov $0xfffff000, %eax;
flush_tlb_others+0x031: 21e0             and %esp, %eax;
flush_tlb_others+0x033: 8b4010           mov 0x10(%eax), %eax;
flush_tlb_others+0x036: 0fa30424         bt %eax, (%esp);
flush_tlb_others+0x03a: 19c0             sbb %eax, %eax;
flush_tlb_others+0x03c: 85c0             test %eax, %eax;
flush_tlb_others+0x03e: 7408             je flush_tlb_others+0x48
flush_tlb_others+0x040: 0f0b             ud2;
flush_tlb_others+0x042: 6a0126032ec0     ; put __LINE__ __FILE__ here for trap 
handler
                                                 362    arch/i386/kernel/smp.c
flush_tlb_others+0x048: 85db             test %ebx, %ebx;
flush_tlb_others+0x04a: 7508             jne flush_tlb_others+0x54
flush_tlb_others+0x04c: 0f0b             ud2;
flush_tlb_others+0x04e: 6b0126032ec0     ; put __LINE__ __FILE__ here for trap 
handler
                                                 363    arch/i386/kernel/smp.c
flush_tlb_others+0x054: b83c1c32c0       mov $0xc0321c3c, %eax;
flush_tlb_others+0x059: e8cd931b00       call <_spin_lock> 
flush_tlb_others+0x05e: 891d609140c0     mov 0xc0409160, %ebx;
flush_tlb_others+0x064: 8b0424           mov (%esp),%eax;
flush_tlb_others+0x067: 8935649140c0     mov %esi, 0xc0409164;  
flush_tlb_others+0x06d: f009055c9140c0   lock or %eax, 0xc040915c;
flush_tlb_others+0x074: 8b0d00f331c0     mov 0xc031f300, %ecx;
flush_tlb_others+0x07a: bafd000000       mov $0xfd, %edx;
flush_tlb_others+0x07f: 8b0424           mov (%esp), %eax;
flush_tlb_others+0x082: ff9180000000     call *0x80(%ecx); 
flush_tlb_others+0x088: eb06             jmp flush_tlb_others+0x90               
flush_tlb_others+0x08a: 0faef0           mfence
flush_tlb_others+0x08d: 8d7600           lea 0x0(%esi), %esi;
flush_tlb_others+0x090: 833d5c9140c000   cmp 0x0, 0xc040915c;     
flush_tlb_others+0x097: 75f1             jne flush_tlb_others+0x8a           
flush_tlb_others+0x099: c705609140c000000000   mov $0x0, 0xc0409160;
flush_tlb_others+0x0a3: b83c1c32c0       mov 0xc0321c3c, %eax 
flush_tlb_others+0x0a8: c705649140c000000000   mov $0x0, 0xc0409164; 
flush_tlb_others+0x0b2: e8e5931b00       call <_spin_unlock>
flush_tlb_others+0x0b7: 5b               pop %ebx;
flush_tlb_others+0x0b8: 5b               pop %ebx;
flush_tlb_others+0x0b9: 5e               pop %esi;
flush_tlb_others+0x0ba: c3               ret;




More information about the Crash-utility mailing list