mkoffsets.sh 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. # automatically compute structure offsets for gcc targets in ELF format
  2. # (C) 2018 Kai-Uwe Bloem. This work is placed in the public domain.
  3. #
  4. # usage: mkoffsets <output dir>
  5. CC=${CC:-gcc}
  6. # endianess of target (automagically determined below)
  7. ENDIAN=
  8. # check which object format to dissect
  9. READELF=
  10. OBJDUMP=
  11. check_obj ()
  12. {
  13. # prepare an object file; as side effect dtermine the endianess
  14. CROSS=$(echo $CC | sed 's/gcc.*//')
  15. echo '#include <stdint.h>' >/tmp/getoffs.c
  16. echo "const int32_t val = 1;" >>/tmp/getoffs.c
  17. $CC $CFLAGS -I .. -c /tmp/getoffs.c -o /tmp/getoffs.o || exit 1
  18. # check for readelf; readelf is the only toolchain tool not using bfd,
  19. # hence it works with ELF files for every target
  20. if file /tmp/getoffs.o | grep -q ELF; then
  21. if command -v readelf >/dev/null; then
  22. READELF=readelf
  23. elif command -v ${CROSS}readelf >/dev/null; then
  24. READELF=${CROSS}readelf
  25. fi
  26. fi
  27. if [ -n "$READELF" ]; then
  28. # find the the .rodata section (in case -fdata-sections is used)
  29. rosect=$($READELF -S /tmp/getoffs.o | grep '\.rodata\|\.sdata' |
  30. sed 's/^[^.]*././;s/ .*//')
  31. # read .rodata section as hex string (should be only 4 bytes)
  32. ro=$($READELF -x $rosect /tmp/getoffs.o | grep '0x' | cut -c14-48 |
  33. tr -d ' \n' | cut -c1-8)
  34. # if no output could be read readelf isn't working
  35. if [ -z "$ro" ]; then
  36. READELF=
  37. fi
  38. fi
  39. # if there is no working readelf try using objdump
  40. if [ -z "$READELF" ]; then
  41. # objdump is using bfd; try using the toolchain objdump first
  42. # since this is likely working with the toolchain objects
  43. if command -v ${CROSS}objdump >/dev/null; then
  44. OBJDUMP=${CROSS}objdump
  45. elif command -v objdump >/dev/null; then
  46. OBJDUMP=objdump
  47. fi
  48. # find the start line of the .rodata section; read the next line
  49. ro=$($OBJDUMP -s /tmp/getoffs.o | awk '\
  50. /Contents of section.*(__const|.r[o]?data|.sdata)/ {o=1; next} \
  51. {if(o) { gsub(/ .*/,""); $1=""; gsub(/ /,""); print; exit}}')
  52. # no working tool for extracting the ro data; stop here
  53. if [ -z "$ro" ]; then
  54. echo "/* mkoffset.sh: no readelf or not ELF, offset table not created */" >$fn
  55. echo "WARNING: no readelf or not ELF, offset table not created"
  56. exit
  57. fi
  58. fi
  59. # extract decimal value from ro
  60. rodata=$(printf "%d" 0x$ro)
  61. ENDIAN=$(if [ "$rodata" -eq 1 ]; then echo be; else echo le; fi)
  62. }
  63. # compile with target C compiler and extract value from .rodata section
  64. compile_rodata ()
  65. {
  66. $CC $CFLAGS -I .. -c /tmp/getoffs.c -o /tmp/getoffs.o || exit 1
  67. if [ -n "$READELF" ]; then
  68. # find the .rodata section (in case -fdata-sections is used)
  69. rosect=$(readelf -S /tmp/getoffs.o | grep '\.rodata\|\.sdata' |
  70. sed 's/^[^.]*././;s/ .*//')
  71. # read .rodata section as hex string (should be only 4 bytes)
  72. ro=$(readelf -x $rosect /tmp/getoffs.o | grep '0x' | cut -c14-48 |
  73. tr -d ' \n' | cut -c1-8)
  74. elif [ -n "$OBJDUMP" ]; then
  75. # find the start line of the .rodata section; read the next line
  76. ro=$($OBJDUMP -s /tmp/getoffs.o | awk '\
  77. /Contents of section.*(__const|.r[o]?data|.sdata)/ {o=1; next} \
  78. {if(o) { gsub(/ .*/,""); $1=""; gsub(/ /,""); print; exit}}')
  79. fi
  80. if [ "$ENDIAN" = "le" ]; then
  81. # swap needed for le target
  82. hex=""
  83. for b in $(echo $ro | sed 's/\([0-9a-f]\{2\}\)/\1 /g'); do
  84. hex=$b$hex;
  85. done
  86. else
  87. hex=$ro
  88. fi
  89. # extract decimal value from hex string
  90. rodata=$(printf "%d" 0x$hex)
  91. }
  92. # determine member offset and create #define
  93. get_define () # prefix struct member member...
  94. {
  95. prefix=$1; shift
  96. struct=$1; shift
  97. field=$(echo $* | sed 's/ /./g')
  98. name=$(echo $* | sed 's/ /_/g')
  99. echo '#include <stdint.h>' > /tmp/getoffs.c
  100. echo '#include <pico/pico_int.h>' >> /tmp/getoffs.c
  101. echo "static struct $struct p;" >> /tmp/getoffs.c
  102. echo "const int32_t val = (char *)&p.$field - (char*)&p;" >>/tmp/getoffs.c
  103. compile_rodata
  104. line=$(printf "#define %-20s 0x%04x" $prefix$name $rodata)
  105. }
  106. fn="${1:-.}/pico_int_offs.h"
  107. if echo $CFLAGS | grep -qe -flto; then CFLAGS="$CFLAGS -fno-lto"; fi
  108. check_obj
  109. # output header
  110. echo "/* autogenerated by mkoffset.sh, do not edit */" >$fn
  111. echo "/* target endianess: $ENDIAN, compiled with: $CC $CFLAGS */" >>$fn
  112. # output offsets
  113. get_define OFS_Pico_ Pico video reg ; echo "$line" >>$fn
  114. get_define OFS_Pico_ Pico m rotate ; echo "$line" >>$fn
  115. get_define OFS_Pico_ Pico m z80Run ; echo "$line" >>$fn
  116. get_define OFS_Pico_ Pico m dirtyPal ; echo "$line" >>$fn
  117. get_define OFS_Pico_ Pico m hardware ; echo "$line" >>$fn
  118. get_define OFS_Pico_ Pico m z80_reset ; echo "$line" >>$fn
  119. get_define OFS_Pico_ Pico m sram_reg ; echo "$line" >>$fn
  120. get_define OFS_Pico_ Pico sv ; echo "$line" >>$fn
  121. get_define OFS_Pico_ Pico sv data ; echo "$line" >>$fn
  122. get_define OFS_Pico_ Pico sv start ; echo "$line" >>$fn
  123. get_define OFS_Pico_ Pico sv end ; echo "$line" >>$fn
  124. get_define OFS_Pico_ Pico sv flags ; echo "$line" >>$fn
  125. get_define OFS_Pico_ Pico rom ; echo "$line" >>$fn
  126. get_define OFS_Pico_ Pico romsize ; echo "$line" >>$fn
  127. get_define OFS_Pico_ Pico est ; echo "$line" >>$fn
  128. get_define OFS_PicoIn_ PicoInterface opt ; echo "$line" >>$fn
  129. get_define OFS_PicoIn_ PicoInterface filter ; echo "$line" >>$fn
  130. get_define OFS_PicoIn_ PicoInterface AHW ; echo "$line" >>$fn
  131. get_define OFS_EST_ PicoEState DrawScanline ; echo "$line" >>$fn
  132. get_define OFS_EST_ PicoEState rendstatus ; echo "$line" >>$fn
  133. get_define OFS_EST_ PicoEState DrawLineDest ; echo "$line" >>$fn
  134. get_define OFS_EST_ PicoEState DrawLineDestIncr ; echo "$line" >>$fn
  135. get_define OFS_EST_ PicoEState HighCol ; echo "$line" >>$fn
  136. get_define OFS_EST_ PicoEState HighPreSpr ; echo "$line" >>$fn
  137. get_define OFS_EST_ PicoEState Pico ; echo "$line" >>$fn
  138. get_define OFS_EST_ PicoEState PicoMem_vram ; echo "$line" >>$fn
  139. get_define OFS_EST_ PicoEState PicoMem_cram ; echo "$line" >>$fn
  140. get_define OFS_EST_ PicoEState PicoOpt ; echo "$line" >>$fn
  141. get_define OFS_EST_ PicoEState Draw2FB ; echo "$line" >>$fn
  142. get_define OFS_EST_ PicoEState Draw2Width ; echo "$line" >>$fn
  143. get_define OFS_EST_ PicoEState Draw2Start ; echo "$line" >>$fn
  144. get_define OFS_EST_ PicoEState HighPal ; echo "$line" >>$fn
  145. get_define OFS_PMEM_ PicoMem vram ; echo "$line" >>$fn
  146. get_define OFS_PMEM_ PicoMem vsram ; echo "$line" >>$fn
  147. get_define OFS_PMEM32x_ Pico32xMem pal_native ; echo "$line" >>$fn
  148. get_define OFS_SH2_ SH2_ is_slave ; echo "$line" >>$fn
  149. get_define OFS_SH2_ SH2_ p_bios ; echo "$line" >>$fn
  150. get_define OFS_SH2_ SH2_ p_da ; echo "$line" >>$fn
  151. get_define OFS_SH2_ SH2_ p_sdram ; echo "$line" >>$fn
  152. get_define OFS_SH2_ SH2_ p_rom ; echo "$line" >>$fn
  153. get_define OFS_SH2_ SH2_ p_dram ; echo "$line" >>$fn
  154. get_define OFS_SH2_ SH2_ p_drcblk_da ; echo "$line" >>$fn
  155. get_define OFS_SH2_ SH2_ p_drcblk_ram ; echo "$line" >>$fn