vivier / qemu-m68k

Other
40 stars 6 forks source link

Python misinterpreting code on qemu-m68k #19

Closed glaubitz closed 7 years ago

glaubitz commented 7 years ago

The following script is part of the Firefox build system:

# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

# This script returns the number of items for the DW_AT_ranges corresponding
# to a given compilation unit. This is used as a helper to find a bug in some
# versions of GNU ld.

from __future__ import absolute_import

import subprocess
import sys
import re

def get_range_for(compilation_unit, debug_info):
    '''Returns the range offset for a given compilation unit
       in a given debug_info.'''
    name = ranges = ''
    search_cu = False
    for nfo in debug_info.splitlines():
        if 'DW_TAG_compile_unit' in nfo:
            search_cu = True
        elif 'DW_TAG_' in nfo or not nfo.strip():                                                                                                 
            if name == compilation_unit and ranges != '':                                                                                         
                return int(ranges, 16)                                                                                                            
            name = ranges = ''                                                                                                                    
            search_cu = False                                                                                                                     
        if search_cu:
            if 'DW_AT_name' in nfo:
                name = nfo.rsplit(None, 1)[1]
            elif 'DW_AT_ranges' in nfo:
                ranges = nfo.rsplit(None, 1)[1]
    return None

def get_range_length(range, debug_ranges):
    '''Returns the number of items in the range starting at the
       given offset.'''
    length = 0
    for line in debug_ranges.splitlines():
        m = re.match('\s*([0-9a-fA-F]+)\s+([0-9a-fA-F]+)\s+([0-9a-fA-F]+)', line)
        if m and int(m.group(1), 16) == range:
            length += 1
    return length

def main(bin, compilation_unit):
    p = subprocess.Popen(['objdump', '-W', bin], stdout = subprocess.PIPE, stderr = subprocess.PIPE)
    (out, err) = p.communicate()
    sections = re.split('\n(Contents of the|The section) ', out)
    debug_info = [s for s in sections if s.startswith('.debug_info')]
    debug_ranges = [s for s in sections if s.startswith('.debug_ranges')]
    if not debug_ranges or not debug_info:
        return 0

    range = get_range_for(compilation_unit, debug_info[0])
    if range is not None:
        return get_range_length(range, debug_ranges[0])

    return -1

if __name__ == '__main__':
    print main(*sys.argv[1:])

During the configure stage of Firefox, it is invoked as follows:

On x86_64:

glaubitz@ikarus:~$ echo 'int foo() {return 42;}'                   'int bar() {return 1;}'                   'int main() {return foo();}' > conftest.c
glaubitz@ikarus:~$ /usr/bin/gcc -std=gnu99 -o conftest.o -specs=/usr/share/dpkg/pie-compile.specs -fstack-protector-strong -Wformat -Werror=format-security -fno-schedule-insns2 -fno-delete-null-pointer-checks -fno-strict-aliasing -ffunction-sections -fdata-sections -fno-math-errno -g -c conftest.c
glaubitz@ikarus:~$ /usr/bin/gcc -std=gnu99 -o conftest -Wl,--as-needed -Wl,--reduce-memory-overheads -Wl,--no-keep-memory -Wl,--stats -Wl,-z,noexecstack -Wl,-z,text -Wl,--build-id -g -Wl,--gc-sections conftest.o
/usr/bin/ld: total time in link: 0.012000
/usr/bin/ld: data size 3788800
glaubitz@ikarus:~$ python check_debug_ranges.py conftest conftest.c
3
glaubitz@ikarus:~$ python check_debug_ranges.py conftest.o conftest.c
3
glaubitz@ikarus:~$

Now, on Aranym:

root@mama:~# echo 'int foo() {return 42;}'                   'int bar() {return 1;}'                   'int main() {return foo();}' > conftest.c
root@mama:~# /usr/bin/gcc -std=gnu99 -o conftest.o -specs=/usr/share/dpkg/pie-compile.specs -fstack-protector-strong -Wformat -Werror=format-security -fno-schedule-insns2 -fno-delete-null-pointer-checks -fno-strict-aliasing -ffunction-sections -fdata-sections -fno-math-errno -g -c conftest.c
root@mama:~# /usr/bin/gcc -std=gnu99 -o conftest -Wl,--as-needed -Wl,--reduce-memory-overheads -Wl,--no-keep-memory -Wl,--stats -Wl,-z,noexecstack -Wl,-z,text -Wl,--build-id -g -Wl,--gc-sections conftest.o
/usr/bin/ld: total time in link: 1.110000
/usr/bin/ld: data size 1409024
root@mama:~# python check_debug_ranges.py conftest conftest.c
3
root@mama:~# python check_debug_ranges.py conftest.o conftest.c
3
root@mama:~#

And, finally, qemu-m68k:

(sid-m68k-sbuild)root@ikarus:/# echo 'int foo() {return 42;}'                   'int bar() {return 1;}'                   'int main() {return foo();}' > conftest.c
(sid-m68k-sbuild)root@ikarus:/# /usr/bin/gcc -std=gnu99 -o conftest.o -specs=/usr/share/dpkg/pie-compile.specs -fstack-protector-strong -Wformat -Werror=format-security -fno-schedule-insns2 -fno-delete-null-pointer-checks -fno-strict-aliasing -ffunction-sections -fdata-sections -fno-math-errno -g -c conftest.c
(sid-m68k-sbuild)root@ikarus:/# /usr/bin/gcc -std=gnu99 -o conftest -Wl,--as-needed -Wl,--reduce-memory-overheads -Wl,--no-keep-memory -Wl,--stats -Wl,-z,noexecstack -Wl,-z,text -Wl,--build-id -g -Wl,--gc-sections conftest.o
/usr/bin/ld: total time in link: 0.132000
/usr/bin/ld: data size 1409024
(sid-m68k-sbuild)root@ikarus:/# python check_debug_ranges.py conftest conftest.c
Traceback (most recent call last):
  File "check_debug_ranges.py", line 62, in <module>
    print main(*sys.argv[1:])
  File "check_debug_ranges.py", line 54, in main
    range = get_range_for(compilation_unit, debug_info[0])
  File "check_debug_ranges.py", line 30, in get_range_for
    name = nfo.rsplit(None, 1)[1]
IndexError: list index out of range
(sid-m68k-sbuild)root@ikarus:/# python check_debug_ranges.py conftest.o conftest.c
Traceback (most recent call last):
  File "check_debug_ranges.py", line 62, in <module>
    print main(*sys.argv[1:])
  File "check_debug_ranges.py", line 54, in main
    range = get_range_for(compilation_unit, debug_info[0])
  File "check_debug_ranges.py", line 30, in get_range_for
    name = nfo.rsplit(None, 1)[1]
IndexError: list index out of range
(sid-m68k-sbuild)root@ikarus:/#
vivier commented 7 years ago

Could you give me the command line to create the chroot?

glaubitz commented 7 years ago

This should help: https://wiki.debian.org/M68k/sbuildQEMU

vivier commented 7 years ago

What is missing?

gcc: note: pie specs /usr/share/dpkg/pie-compile.specs ignored when pie is not enabled

glaubitz commented 7 years ago

That's just a warning in conjunction with the gcc hardening settings. You can safely ignore it.

vivier commented 7 years ago

The problem is in this sequence:


IN: 0xf6da000c: moveal %a5@(6c8),%a0 0xf6da0014: clrl %d0 0xf6da0016: moveb %a3@(0,%d2:l),%d0 0xf6da001a: btst #3,%a0@(3,%d0:l:4) 0xf6da0020: dbeq %d2,0xf6da0014


IN: 0xf6da0014: clrl %d0 0xf6da0016: moveb %a3@(0,%d2:l),%d0 0xf6da001a: btst #3,%a0@(3,%d0:l:4) 0xf6da0020: dbeq %d2,0xf6da0014

"0xf6da001a: btst" does a flush_flags() because it only updates the Z flag. flush_flags() set cc_op_synced to 1 and s->cc_op to CC_OP_FLAGS. but env->cc_op can have a different value, so cc_op_synced is wrong.

Fixed by commit:

843cd25 target-m68k: fix gen_flush_flags()