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
|
This is a first attempt to document the grammar used by magic(5), with
hopes of eventually incorporating something like this into the manpage.
Note: Currently, the parser varies slightly from this, but only in
very minor ways, e.g., the strflags maybe separated by '/' characters
and at most one strcount is allowed; likewise for regflags.
------------------------------------------------------------------------
magic = 1*query
query = line *( 1*level line )
level = ">" ;; Increment the level by 1.
;; The first line of a query is at level 0.
line = offset HWS type HWS test HWS message EOL
------------------------------------------------------------------------
offset = absoffset | reloffset | indoffset
;; The offset in the file at which to apply
;; the <test>.
absoffset = NUMBER ;; An absolute offset from the start of the file.
reloffset = "&" NUMBER ;; The offset relative to the last match offset
;; at one level up.
;; Not allowed at level == 0.
indoffset = indoff | relindoff
indoff = "(" offset1 [ "." size ] [ op disp ] ")"
;; Read the file at <offset1> of width <size>.
;; If size is not specified, assume a long.
;; If <op> is given, then preform that
;; operation on the result and the <disp>.
offset1 = absoffset | reloffset
size = byte | leshort | beshort | lelong | belong | melong
byte = "B" | "b" | "C" | "c" ;; A one-byte value.
leshort = "s" | "h" ;; A two-byte little-endian value.
beshort = "S" | "H" ;; A two-byte big-endian value.
lelong = "l" ;; A four-byte little-endian value.
belong = "L" ;; A four-byte big-endian value.
melong = "m" ;; A four-byte middle-endian value.
op = [ invert ] ( "+" | "-" | "*" | "/" | "%" | "&" | "|" | "^" )
invert = "~" ;; Flip the bits on result of the <op>.
disp = NUMBER | memvalue
memvalue = "(" NUMBER ")"
;; NUMBER is interpreted as an absolute or
;; relative offset matching that of <offset1>.
;; Read the file at the resulting offset with
;; the same size as <offset1>
relindoff = "&" indoff ;; add <indoff> to the last match offset at
;; one level up.
------------------------------------------------------------------------
type = [ unsigned ] ( numeric | strtype | default )
unsigned = "u" ;; The value is unsigned.
;; This affects the sign extension of numeric
;; types and the '<' and '>' compares. It is
;; intended for numeric types, but allowed on
;; all types.
numeric = ( numtype | datatype ) [ nummask ]
numtype = byte | short | long | quad
byte = "byte"
short = "short" | "beshort" | "leshort"
long = "long" | "lelong" | "belong" | "melong"
quad = "quad" | "lequad" | "bequad"
datetype = udate32 | ldate32 | udate64 | ldate64
udate32 = "date" | "bedate" | "ledate" | "medate" ;; UTC dates
ldate32 = "ldate" | "beldate" | "leldate" | "meldate" ;; local dates
udate64 = "qdate" | "leqdate" | "beqdate" ;; UTC dates
ldate64 = "qldate" | "leqldate" | "beqldate" ;; local dates
nummask = op NUMBER
strtype = regex | search | string8 | string16
regex = "regex" [ "/" 1*regflag ]
regflag = "c" | "s" | linecnt
linecnt = NUMBER ;; The number of lines to search. If this
;; is missing or zero, the rest of the
;; file is searched.
search = "string" [ "/" 1*srchflag ]
srchflag = strflag | srchcnt
srchcnt = NUMBER ;; The number of search tries. If this
;; is missing or zero, the rest of the
;; file is searched.
string8 = ( "string" | "pstring" ) [ "/" 1*strflag ]
strflag = "b" | "B" | "c" | "C"
string16 = "bestring16" | "lestring16"
default = "default" ;; This is intended to be used with the
;; <truetest> ("x" below). It is matched if
;; there has been no previous match at its
;; level or none since the last default at
;; that level. It is useful for implementing
;; switch-like and if/else constructions.
------------------------------------------------------------------------
test = numtest | strtest | truetest
;; Test to preform on <type> read from file.
numtest = [ compare ] NUMBER ;; If compare is missing, "=" is assumed.
strtest = [ compare ] STRING ;; If compare is missing, "=" is assumed.
;; Note: If the STRING begins with a <compare>
;; character, the <compare> field cannot be
;; omitted.
compare = "=" | "!" | "<" | ">" | "&" | "^"
truetest = "x" ;; This always returns true.
;; To test for the string "x" use "=x".
------------------------------------------------------------------------
message = [ nospflag ] ( STRING | FMT_STRING )
;; Message to print if test result is true.
nospflag = %x08 | "\\b" ;; Do not insert a space before the message.
;; By default, messages are separated by a " ".
------------------------------------------------------------------------
HWS = <horizontal white space>
EOL = <end of line marker>
NUMBER = <C-style unsigned number>
STRING = <C-style string without delimiting quotes>
FMTSTR = <printf format string with exactly one % construct>
------------------------------------------------------------------------
|