102 if (tmp->ident &&
103 strcmp(member_name, tmp->ident->name) == 0) {
104 return offset;
105 }
106 if (matches_anonymous_union(tmp, member_name))
107 return offset;
108 if (!(type_bits(tmp) % 8) && type_bits(tmp) / 8 == type_bytes(tmp))
109 offset += type_bytes(tmp);
110 else
111 bits += type_bits(tmp);
112 } END_FOR_EACH_PTR(tmp);
113 return -1;
114 }
115
116 int get_member_offset_from_deref(struct expression *expr)
117 {
118 struct symbol *type;
119 struct ident *member;
120 int offset;
121
122 if (expr->type != EXPR_DEREF) /* hopefully, this doesn't happen */
123 return -1;
124
125 if (expr->member_offset >= 0)
126 return expr->member_offset;
127
128 member = expr->member;
129 if (!member)
130 return -1;
131
132 type = get_type(expr->deref);
133 if (type_is_ptr(type))
134 type = get_real_base_type(type);
135 if (!type || type->type != SYM_STRUCT)
136 return -1;
137
138 offset = get_member_offset(type, member->name);
139 if (offset >= 0)
140 expr->member_offset = offset;
141 return offset;
185
186 /* no wrap around */
187 max.uvalue = rl_max(orig).uvalue;
188 if (max.uvalue > sval_type_max(&ptr_ctype).uvalue - offset) {
189 remove = sval_type_max(&ptr_ctype);
190 remove.uvalue -= offset;
191 orig = remove_range(orig, remove, max);
192 }
193
194 sval.type = &int_ctype;
195 sval.value = offset;
196
197 *rl = rl_binop(orig, '+', alloc_rl(sval, sval));
198 }
199
200 static struct range_list *where_allocated_rl(struct symbol *sym)
201 {
202 if (!sym)
203 return NULL;
204
205 return alloc_rl(valid_ptr_min_sval, valid_ptr_max_sval);
206 }
207
208 int get_address_rl(struct expression *expr, struct range_list **rl)
209 {
210 struct expression *unop;
211
212 expr = strip_expr(expr);
213 if (!expr)
214 return 0;
215
216 if (expr->type == EXPR_STRING) {
217 *rl = alloc_rl(valid_ptr_min_sval, valid_ptr_max_sval);
218 return 1;
219 }
220
221 if (expr->type == EXPR_PREOP && expr->op == '&')
222 expr = strip_expr(expr->unop);
223 else {
224 struct symbol *type;
225
226 type = get_type(expr);
227 if (!type || type->type != SYM_ARRAY)
228 return 0;
229 }
230
231 if (expr->type == EXPR_SYMBOL) {
232 *rl = where_allocated_rl(expr->symbol);
233 return 1;
234 }
235
236 if (is_array(expr)) {
237 struct expression *array;
238 struct expression *offset_expr;
239 struct range_list *array_rl, *offset_rl, *bytes_rl, *res;
240 struct symbol *type;
241 sval_t bytes;
242
243 array = get_array_base(expr);
|
102 if (tmp->ident &&
103 strcmp(member_name, tmp->ident->name) == 0) {
104 return offset;
105 }
106 if (matches_anonymous_union(tmp, member_name))
107 return offset;
108 if (!(type_bits(tmp) % 8) && type_bits(tmp) / 8 == type_bytes(tmp))
109 offset += type_bytes(tmp);
110 else
111 bits += type_bits(tmp);
112 } END_FOR_EACH_PTR(tmp);
113 return -1;
114 }
115
116 int get_member_offset_from_deref(struct expression *expr)
117 {
118 struct symbol *type;
119 struct ident *member;
120 int offset;
121
122 /*
123 * FIXME: This doesn't handle foo.u.bar correctly.
124 *
125 */
126
127 if (expr->type != EXPR_DEREF) /* hopefully, this doesn't happen */
128 return -1;
129
130 if (expr->member_offset >= 0)
131 return expr->member_offset;
132
133 member = expr->member;
134 if (!member)
135 return -1;
136
137 type = get_type(expr->deref);
138 if (type_is_ptr(type))
139 type = get_real_base_type(type);
140 if (!type || type->type != SYM_STRUCT)
141 return -1;
142
143 offset = get_member_offset(type, member->name);
144 if (offset >= 0)
145 expr->member_offset = offset;
146 return offset;
190
191 /* no wrap around */
192 max.uvalue = rl_max(orig).uvalue;
193 if (max.uvalue > sval_type_max(&ptr_ctype).uvalue - offset) {
194 remove = sval_type_max(&ptr_ctype);
195 remove.uvalue -= offset;
196 orig = remove_range(orig, remove, max);
197 }
198
199 sval.type = &int_ctype;
200 sval.value = offset;
201
202 *rl = rl_binop(orig, '+', alloc_rl(sval, sval));
203 }
204
205 static struct range_list *where_allocated_rl(struct symbol *sym)
206 {
207 if (!sym)
208 return NULL;
209
210 /* This should just be the mtag if it's not on the stack */
211 return alloc_rl(valid_ptr_min_sval, valid_ptr_max_sval);
212 }
213
214 static bool handle_fn_address(struct expression *expr, struct range_list **rl)
215 {
216 struct symbol *type;
217
218 if (expr->type == EXPR_PREOP && expr->op == '&')
219 expr = strip_expr(expr->unop);
220
221 if (expr->type != EXPR_SYMBOL)
222 return false;
223
224 type = get_type(expr);
225 if (!type || type->type != SYM_FN)
226 return false;
227
228 *rl = alloc_rl(valid_ptr_min_sval, valid_ptr_max_sval);
229 return true;
230 }
231
232 int get_address_rl(struct expression *expr, struct range_list **rl)
233 {
234 struct expression *unop;
235
236 /*
237 * Ugh... This function is bad. It doesn't work where it's supposed to
238 * and it does more than it really should. It shouldn't handle string
239 * literals I think...
240 *
241 * There are several complications. For arrays and functions the "&foo"
242 * "foo" are equivalent. But the problem is that we're also passing in
243 * foo->array[] and foo->fn.
244 *
245 * Then, when we have foo->bar.baz.one.two; that needs to be handled
246 * correctly but right now, it is not.
247 *
248 */
249
250 expr = strip_expr(expr);
251 if (!expr)
252 return 0;
253
254 /*
255 * For functions &fn and fn are equivalent. I don't know if this is
256 * really the right place to handle it, but let's just get it out of the
257 * way for now.
258 *
259 */
260 if (handle_fn_address(expr, rl))
261 return 1;
262
263 /*
264 * For arrays, &foo->array and foo->array are equivalent.
265 *
266 */
267 if (expr->type == EXPR_PREOP && expr->op == '&') {
268 expr = strip_expr(expr->unop);
269 } else {
270 struct symbol *type;
271
272 type = get_type(expr);
273 if (!type || type->type != SYM_ARRAY)
274 return 0;
275 }
276
277 if (expr->type == EXPR_SYMBOL) {
278 *rl = where_allocated_rl(expr->symbol);
279 return 1;
280 }
281
282 if (is_array(expr)) {
283 struct expression *array;
284 struct expression *offset_expr;
285 struct range_list *array_rl, *offset_rl, *bytes_rl, *res;
286 struct symbol *type;
287 sval_t bytes;
288
289 array = get_array_base(expr);
|