123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166 |
- # automatically compute structure offsets for gcc targets in ELF format
- # (C) 2018 Kai-Uwe Bloem. This work is placed in the public domain.
- #
- # usage: mkoffsets <output dir>
- CC=${CC:-gcc}
- # endianess of target (automagically determined below)
- ENDIAN=
- # check which object format to dissect
- READELF=
- OBJDUMP=
- check_obj ()
- {
- # prepare an object file; as side effect dtermine the endianess
- CROSS=$(echo $CC | sed 's/gcc.*//')
- echo '#include <stdint.h>' >/tmp/getoffs.c
- echo "const int32_t val = 1;" >>/tmp/getoffs.c
- $CC $CFLAGS -I .. -c /tmp/getoffs.c -o /tmp/getoffs.o || exit 1
- # check for readelf; readelf is the only toolchain tool not using bfd,
- # hence it works with ELF files for every target
- if file /tmp/getoffs.o | grep -q ELF; then
- if command -v readelf >/dev/null; then
- READELF=readelf
- elif command -v ${CROSS}readelf >/dev/null; then
- READELF=${CROSS}readelf
- fi
- fi
- if [ -n "$READELF" ]; then
- # find the the .rodata section (in case -fdata-sections is used)
- rosect=$($READELF -S /tmp/getoffs.o | grep '\.rodata\|\.sdata' |
- sed 's/^[^.]*././;s/ .*//')
- # read .rodata section as hex string (should be only 4 bytes)
- ro=$($READELF -x $rosect /tmp/getoffs.o | grep '0x' | cut -c14-48 |
- tr -d ' \n' | cut -c1-8)
- # if no output could be read readelf isn't working
- if [ -z "$ro" ]; then
- READELF=
- fi
- fi
- # if there is no working readelf try using objdump
- if [ -z "$READELF" ]; then
- # objdump is using bfd; try using the toolchain objdump first
- # since this is likely working with the toolchain objects
- if command -v ${CROSS}objdump >/dev/null; then
- OBJDUMP=${CROSS}objdump
- elif command -v objdump >/dev/null; then
- OBJDUMP=objdump
- fi
- # find the start line of the .rodata section; read the next line
- ro=$($OBJDUMP -s /tmp/getoffs.o | awk '\
- /Contents of section.*(__const|.r[o]?data|.sdata)/ {o=1; next} \
- {if(o) { gsub(/ .*/,""); $1=""; gsub(/ /,""); print; exit}}')
- # no working tool for extracting the ro data; stop here
- if [ -z "$ro" ]; then
- echo "/* mkoffset.sh: no readelf or not ELF, offset table not created */" >$fn
- echo "WARNING: no readelf or not ELF, offset table not created"
- exit
- fi
- fi
- # extract decimal value from ro
- rodata=$(printf "%d" 0x$ro)
- ENDIAN=$(if [ "$rodata" -eq 1 ]; then echo be; else echo le; fi)
- }
- # compile with target C compiler and extract value from .rodata section
- compile_rodata ()
- {
- $CC $CFLAGS -I .. -c /tmp/getoffs.c -o /tmp/getoffs.o || exit 1
- if [ -n "$READELF" ]; then
- # find the .rodata section (in case -fdata-sections is used)
- rosect=$(readelf -S /tmp/getoffs.o | grep '\.rodata\|\.sdata' |
- sed 's/^[^.]*././;s/ .*//')
- # read .rodata section as hex string (should be only 4 bytes)
- ro=$(readelf -x $rosect /tmp/getoffs.o | grep '0x' | cut -c14-48 |
- tr -d ' \n' | cut -c1-8)
- elif [ -n "$OBJDUMP" ]; then
- # find the start line of the .rodata section; read the next line
- ro=$($OBJDUMP -s /tmp/getoffs.o | awk '\
- /Contents of section.*(__const|.r[o]?data|.sdata)/ {o=1; next} \
- {if(o) { gsub(/ .*/,""); $1=""; gsub(/ /,""); print; exit}}')
- fi
- if [ "$ENDIAN" = "le" ]; then
- # swap needed for le target
- hex=""
- for b in $(echo $ro | sed 's/\([0-9a-f]\{2\}\)/\1 /g'); do
- hex=$b$hex;
- done
- else
- hex=$ro
- fi
- # extract decimal value from hex string
- rodata=$(printf "%d" 0x$hex)
- }
- # determine member offset and create #define
- get_define () # prefix struct member member...
- {
- prefix=$1; shift
- struct=$1; shift
- field=$(echo $* | sed 's/ /./g')
- name=$(echo $* | sed 's/ /_/g')
- echo '#include <stdint.h>' > /tmp/getoffs.c
- echo '#include <pico/pico_int.h>' >> /tmp/getoffs.c
- echo "static struct $struct p;" >> /tmp/getoffs.c
- echo "const int32_t val = (char *)&p.$field - (char*)&p;" >>/tmp/getoffs.c
- compile_rodata
- line=$(printf "#define %-20s 0x%04x" $prefix$name $rodata)
- }
- fn="${1:-.}/pico_int_offs.h"
- if echo $CFLAGS | grep -qe -flto; then CFLAGS="$CFLAGS -fno-lto"; fi
- check_obj
- # output header
- echo "/* autogenerated by mkoffset.sh, do not edit */" >$fn
- echo "/* target endianess: $ENDIAN, compiled with: $CC $CFLAGS */" >>$fn
- # output offsets
- get_define OFS_Pico_ Pico video reg ; echo "$line" >>$fn
- get_define OFS_Pico_ Pico m rotate ; echo "$line" >>$fn
- get_define OFS_Pico_ Pico m z80Run ; echo "$line" >>$fn
- get_define OFS_Pico_ Pico m dirtyPal ; echo "$line" >>$fn
- get_define OFS_Pico_ Pico m hardware ; echo "$line" >>$fn
- get_define OFS_Pico_ Pico m z80_reset ; echo "$line" >>$fn
- get_define OFS_Pico_ Pico m sram_reg ; echo "$line" >>$fn
- get_define OFS_Pico_ Pico sv ; echo "$line" >>$fn
- get_define OFS_Pico_ Pico sv data ; echo "$line" >>$fn
- get_define OFS_Pico_ Pico sv start ; echo "$line" >>$fn
- get_define OFS_Pico_ Pico sv end ; echo "$line" >>$fn
- get_define OFS_Pico_ Pico sv flags ; echo "$line" >>$fn
- get_define OFS_Pico_ Pico rom ; echo "$line" >>$fn
- get_define OFS_Pico_ Pico romsize ; echo "$line" >>$fn
- get_define OFS_Pico_ Pico est ; echo "$line" >>$fn
- get_define OFS_PicoIn_ PicoInterface opt ; echo "$line" >>$fn
- get_define OFS_PicoIn_ PicoInterface filter ; echo "$line" >>$fn
- get_define OFS_EST_ PicoEState DrawScanline ; echo "$line" >>$fn
- get_define OFS_EST_ PicoEState rendstatus ; echo "$line" >>$fn
- get_define OFS_EST_ PicoEState DrawLineDest ; echo "$line" >>$fn
- get_define OFS_EST_ PicoEState DrawLineDestIncr ; echo "$line" >>$fn
- get_define OFS_EST_ PicoEState HighCol ; echo "$line" >>$fn
- get_define OFS_EST_ PicoEState HighPreSpr ; echo "$line" >>$fn
- get_define OFS_EST_ PicoEState Pico ; echo "$line" >>$fn
- get_define OFS_EST_ PicoEState PicoMem_vram ; echo "$line" >>$fn
- get_define OFS_EST_ PicoEState PicoMem_cram ; echo "$line" >>$fn
- get_define OFS_EST_ PicoEState PicoOpt ; echo "$line" >>$fn
- get_define OFS_EST_ PicoEState Draw2FB ; echo "$line" >>$fn
- get_define OFS_EST_ PicoEState Draw2Width ; echo "$line" >>$fn
- get_define OFS_EST_ PicoEState Draw2Start ; echo "$line" >>$fn
- get_define OFS_EST_ PicoEState HighPal ; echo "$line" >>$fn
- get_define OFS_PMEM_ PicoMem vram ; echo "$line" >>$fn
- get_define OFS_PMEM_ PicoMem vsram ; echo "$line" >>$fn
- get_define OFS_PMEM32x_ Pico32xMem pal_native ; echo "$line" >>$fn
- get_define OFS_SH2_ SH2_ is_slave ; echo "$line" >>$fn
- get_define OFS_SH2_ SH2_ p_bios ; echo "$line" >>$fn
- get_define OFS_SH2_ SH2_ p_da ; echo "$line" >>$fn
- get_define OFS_SH2_ SH2_ p_sdram ; echo "$line" >>$fn
- get_define OFS_SH2_ SH2_ p_rom ; echo "$line" >>$fn
- get_define OFS_SH2_ SH2_ p_dram ; echo "$line" >>$fn
- get_define OFS_SH2_ SH2_ p_drcblk_da ; echo "$line" >>$fn
- get_define OFS_SH2_ SH2_ p_drcblk_ram ; echo "$line" >>$fn
|