1 /***************************************************************************************************
2
3 Zyan Disassembler Library (Zydis)
4
5 Original Author : Florian Bernd
6
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in all
15 * copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24
25 ***************************************************************************************************/
26
27 #include <Zydis/Internal/String.h>
28 #include <Zydis/FormatterBuffer.h>
29
30 /* ============================================================================================== */
31 /* Exported functions */
32 /* ============================================================================================== */
33
34 /* ---------------------------------------------------------------------------------------------- */
35 /* Token */
36 /* ---------------------------------------------------------------------------------------------- */
37
ZydisFormatterTokenGetValue(const ZydisFormatterToken * token,ZydisTokenType * type,ZyanConstCharPointer * value)38 ZyanStatus ZydisFormatterTokenGetValue(const ZydisFormatterToken* token,
39 ZydisTokenType* type, ZyanConstCharPointer* value)
40 {
41 if (!token || !type || !value)
42 {
43 return ZYAN_STATUS_INVALID_ARGUMENT;
44 }
45
46 *type = token->type;
47 *value = (ZyanConstCharPointer)((ZyanU8*)token + sizeof(ZydisFormatterToken));
48
49 return ZYAN_STATUS_SUCCESS;
50 }
51
ZydisFormatterTokenNext(ZydisFormatterTokenConst ** token)52 ZyanStatus ZydisFormatterTokenNext(ZydisFormatterTokenConst** token)
53 {
54 if (!token || !*token)
55 {
56 return ZYAN_STATUS_INVALID_ARGUMENT;
57 }
58
59 const ZyanU8 next = (*token)->next;
60 if (!next)
61 {
62 return ZYAN_STATUS_OUT_OF_RANGE;
63 }
64 *token = (ZydisFormatterTokenConst*)((ZyanU8*)*token + sizeof(ZydisFormatterToken) + next);
65
66 return ZYAN_STATUS_SUCCESS;
67 }
68
69 /* ---------------------------------------------------------------------------------------------- */
70 /* Buffer */
71 /* ---------------------------------------------------------------------------------------------- */
72
ZydisFormatterBufferGetToken(const ZydisFormatterBuffer * buffer,ZydisFormatterTokenConst ** token)73 ZyanStatus ZydisFormatterBufferGetToken(const ZydisFormatterBuffer* buffer,
74 ZydisFormatterTokenConst** token)
75 {
76 if (!buffer || !token)
77 {
78 return ZYAN_STATUS_INVALID_ARGUMENT;
79 }
80
81 *token = ((ZydisFormatterTokenConst*)buffer->string.vector.data - 1);
82 if ((*token)->type == ZYDIS_TOKEN_INVALID)
83 {
84 return ZYAN_STATUS_INVALID_OPERATION;
85 }
86
87 return ZYAN_STATUS_SUCCESS;
88 }
89
ZydisFormatterBufferGetString(ZydisFormatterBuffer * buffer,ZyanString ** string)90 ZyanStatus ZydisFormatterBufferGetString(ZydisFormatterBuffer* buffer, ZyanString** string)
91 {
92 if (!buffer || !string)
93 {
94 return ZYAN_STATUS_INVALID_ARGUMENT;
95 }
96
97 if (buffer->is_token_list &&
98 ((ZydisFormatterTokenConst*)buffer->string.vector.data - 1)->type == ZYDIS_TOKEN_INVALID)
99 {
100 return ZYAN_STATUS_INVALID_OPERATION;
101 }
102
103 ZYAN_ASSERT(buffer->string.vector.data);
104 ZYAN_ASSERT(buffer->string.vector.size);
105
106 *string = &buffer->string;
107
108 return ZYAN_STATUS_SUCCESS;
109 }
110
ZydisFormatterBufferAppend(ZydisFormatterBuffer * buffer,ZydisTokenType type)111 ZyanStatus ZydisFormatterBufferAppend(ZydisFormatterBuffer* buffer, ZydisTokenType type)
112 {
113 if (!buffer)
114 {
115 return ZYAN_STATUS_INVALID_ARGUMENT;
116 }
117
118 if (!buffer->is_token_list)
119 {
120 return ZYAN_STATUS_SUCCESS;
121 }
122
123 const ZyanUSize len = buffer->string.vector.size;
124 ZYAN_ASSERT((len > 0) && (len < 256));
125 if (buffer->capacity <= len + sizeof(ZydisFormatterToken))
126 {
127 return ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE;
128 }
129
130 ZydisFormatterToken* const last = (ZydisFormatterToken*)buffer->string.vector.data - 1;
131 last->next = (ZyanU8)len;
132
133 const ZyanUSize delta = len + sizeof(ZydisFormatterToken);
134 buffer->capacity -= delta;
135 buffer->string.vector.data = (ZyanU8*)buffer->string.vector.data + delta;
136 buffer->string.vector.size = 1;
137 buffer->string.vector.capacity = ZYAN_MIN(buffer->capacity, 255);
138 *(char*)buffer->string.vector.data = '\0';
139
140 ZydisFormatterToken* const token = (ZydisFormatterToken*)buffer->string.vector.data - 1;
141 token->type = type;
142 token->next = 0;
143
144 return ZYAN_STATUS_SUCCESS;
145 }
146
ZydisFormatterBufferRemember(const ZydisFormatterBuffer * buffer,ZyanUPointer * state)147 ZyanStatus ZydisFormatterBufferRemember(const ZydisFormatterBuffer* buffer, ZyanUPointer* state)
148 {
149 if (!buffer || !state)
150 {
151 return ZYAN_STATUS_INVALID_ARGUMENT;
152 }
153
154 if (buffer->is_token_list)
155 {
156 *state = (ZyanUPointer)buffer->string.vector.data;
157 } else
158 {
159 *state = (ZyanUPointer)buffer->string.vector.size;
160 }
161
162 return ZYAN_STATUS_SUCCESS;
163 }
164
ZydisFormatterBufferRestore(ZydisFormatterBuffer * buffer,ZyanUPointer state)165 ZyanStatus ZydisFormatterBufferRestore(ZydisFormatterBuffer* buffer, ZyanUPointer state)
166 {
167 if (!buffer)
168 {
169 return ZYAN_STATUS_INVALID_ARGUMENT;
170 }
171
172 if (buffer->is_token_list)
173 {
174 const ZyanUSize delta = (ZyanUPointer)buffer->string.vector.data - state;
175 buffer->capacity += delta;
176 buffer->string.vector.data = (void*)state;
177 buffer->string.vector.size = 1; // TODO: Restore size?
178 buffer->string.vector.capacity = ZYAN_MIN(buffer->capacity, 255);
179 *(char*)buffer->string.vector.data = '\0';
180 } else
181 {
182 buffer->string.vector.size = (ZyanUSize)state;
183 ZYDIS_STRING_NULLTERMINATE(&buffer->string);
184 }
185
186 return ZYAN_STATUS_SUCCESS;
187 }
188
189 /* ---------------------------------------------------------------------------------------------- */
190
191 /* ============================================================================================== */
192