forked from notaz/picodrive
-
Notifications
You must be signed in to change notification settings - Fork 65
/
Copy pathmkoffsets.sh
executable file
·167 lines (155 loc) · 6.54 KB
/
mkoffsets.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# 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_PicoIn_ PicoInterface AHW ; 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