fetch.c revision bac2da505ee174b7fb984b975c5938f88f0dbab2
1/* 2 * This file is part of ltrace. 3 * Copyright (C) 2011,2012 Petr Machata 4 * 5 * This program is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU General Public License as 7 * published by the Free Software Foundation; either version 2 of the 8 * License, or (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, but 11 * WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 18 * 02110-1301 USA 19 */ 20 21#include "config.h" 22 23#include <sys/types.h> 24#include <assert.h> 25#include <gelf.h> 26#include <stddef.h> 27#include <stdint.h> 28#include <stdlib.h> 29#include <string.h> 30 31#include "backend.h" 32#include "expr.h" 33#include "fetch.h" 34#include "proc.h" 35#include "ptrace.h" 36#include "type.h" 37#include "value.h" 38 39enum arg_class { 40 CLASS_INTEGER, 41 CLASS_SSE, 42 CLASS_NO, 43 CLASS_MEMORY, 44 CLASS_X87, 45}; 46 47enum reg_pool { 48 POOL_FUNCALL, 49 POOL_SYSCALL, 50 /* A common pool for system call and function call return is 51 * enough, the ABI is similar enough. */ 52 POOL_RETVAL, 53}; 54 55struct fetch_context 56{ 57 struct user_regs_struct iregs; 58 struct user_fpregs_struct fpregs; 59 60 void *stack_pointer; 61 size_t ireg; /* Used-up integer registers. */ 62 size_t freg; /* Used-up floating registers. */ 63 64 union { 65 struct { 66 /* Storage classes for return type. We need 67 * to compute them anyway, so let's keep them 68 * around. */ 69 enum arg_class ret_classes[2]; 70 ssize_t num_ret_classes; 71 } x86_64; 72 struct { 73 struct value retval; 74 } ix86; 75 } u; 76}; 77 78#ifndef __x86_64__ 79__attribute__((noreturn)) static void 80i386_unreachable(void) 81{ 82 abort(); 83} 84#endif 85 86static int 87contains_unaligned_fields(struct arg_type_info *info) 88{ 89 /* XXX currently we don't support structure alignment. */ 90 return 0; 91} 92 93static int 94has_nontrivial_ctor_dtor(struct arg_type_info *info) 95{ 96 /* XXX another unsupported aspect of type info. We might call 97 * these types "class" instead of "struct" in the config 98 * file. */ 99 return 0; 100} 101 102static void 103copy_int_register(struct fetch_context *context, 104 struct value *valuep, unsigned long val, size_t offset) 105{ 106 if (valuep != NULL) { 107 unsigned char *buf = value_get_raw_data(valuep); 108 memcpy(buf + offset, &val, sizeof(val)); 109 } 110 context->ireg++; 111} 112 113static void 114copy_sse_register(struct fetch_context *context, struct value *valuep, 115 int half, size_t sz, size_t offset) 116{ 117#ifdef __x86_64__ 118 union { 119 uint32_t sse[4]; 120 long halves[2]; 121 } u; 122 size_t off = 4 * context->freg++; 123 memcpy(u.sse, context->fpregs.xmm_space + off, sizeof(u.sse)); 124 125 if (valuep != NULL) { 126 unsigned char *buf = value_get_raw_data(valuep); 127 memcpy(buf + offset, u.halves + half, sz); 128 } 129#else 130 i386_unreachable(); 131#endif 132} 133 134static void 135allocate_stack_slot(struct fetch_context *context, 136 struct value *valuep, size_t sz, size_t offset, 137 size_t archw) 138{ 139 size_t a = type_alignof(valuep->inferior, valuep->type); 140 if (a < archw) 141 a = archw; 142 context->stack_pointer 143 = (void *)align((unsigned long)context->stack_pointer, a); 144 145 if (valuep != NULL) { 146 valuep->where = VAL_LOC_INFERIOR; 147 valuep->u.address = context->stack_pointer; 148 } 149 context->stack_pointer += sz; 150} 151 152static enum arg_class 153allocate_x87(struct fetch_context *context, struct value *valuep, 154 size_t sz, size_t offset, enum reg_pool pool, size_t archw) 155{ 156 /* Both i386 and x86_64 ABI only ever really use x87 registers 157 * to return values. Otherwise, the parameter is treated as 158 * if it were CLASS_MEMORY. On x86_64 x87 registers are only 159 * used for returning long double values, which we currently 160 * don't support. */ 161 162 if (pool != POOL_RETVAL) { 163 allocate_stack_slot(context, valuep, sz, offset, archw); 164 return CLASS_MEMORY; 165 166 } 167 168 /* If the class is X87, the value is returned on the X87 stack 169 * in %st0 as 80-bit x87 number. 170 * 171 * If the class is X87UP, the value is returned together with 172 * the previous X87 value in %st0. 173 * 174 * If the class is COMPLEX_X87, the real part of the value is 175 * returned in %st0 and the imaginary part in %st1. */ 176 177 if (valuep != NULL) { 178 union { 179 long double ld; 180 double d; 181 float f; 182 char buf[0]; 183 } u; 184 185 /* The x87 floating point value is in long double 186 * format, so we need to convert in to the right type. 187 * Alternatively we might just leave it as is and 188 * smuggle the long double type into the value (via 189 * value_set_type), but for that we first need to 190 * support long double in the first place. */ 191 192#ifdef __x86_64__ 193 unsigned int *reg; 194#else 195 long int *reg; 196#endif 197 reg = &context->fpregs.st_space[0]; 198 memcpy(&u.ld, reg, sizeof(u)); 199 if (valuep->type->type == ARGTYPE_FLOAT) 200 u.f = (float)u.ld; 201 else if (valuep->type->type == ARGTYPE_DOUBLE) 202 u.d = (double)u.ld; 203 else 204 assert(!"Unexpected floating type!"), abort(); 205 206 unsigned char *buf = value_get_raw_data(valuep); 207 memcpy(buf + offset, u.buf, sz); 208 } 209 return CLASS_X87; 210} 211 212static enum arg_class 213allocate_integer(struct fetch_context *context, struct value *valuep, 214 size_t sz, size_t offset, enum reg_pool pool) 215{ 216#define HANDLE(NUM, WHICH) \ 217 case NUM: \ 218 copy_int_register(context, valuep, \ 219 context->iregs.WHICH, offset); \ 220 return CLASS_INTEGER 221 222 switch (pool) { 223 case POOL_FUNCALL: 224#ifdef __x86_64__ 225 switch (context->ireg) { 226 HANDLE(0, rdi); 227 HANDLE(1, rsi); 228 HANDLE(2, rdx); 229 HANDLE(3, rcx); 230 HANDLE(4, r8); 231 HANDLE(5, r9); 232 default: 233 allocate_stack_slot(context, valuep, sz, offset, 8); 234 return CLASS_MEMORY; 235 } 236#else 237 i386_unreachable(); 238#endif 239 240 case POOL_SYSCALL: 241#ifdef __x86_64__ 242 switch (context->ireg) { 243 HANDLE(0, rdi); 244 HANDLE(1, rsi); 245 HANDLE(2, rdx); 246 HANDLE(3, r10); 247 HANDLE(4, r8); 248 HANDLE(5, r9); 249 default: 250 assert(!"More than six syscall arguments???"); 251 abort(); 252 } 253#else 254 i386_unreachable(); 255#endif 256 257 case POOL_RETVAL: 258 switch (context->ireg) { 259#ifdef __x86_64__ 260 HANDLE(0, rax); 261 HANDLE(1, rdx); 262#else 263 HANDLE(0, eax); 264#endif 265 default: 266 assert(!"Too many return value classes."); 267 abort(); 268 } 269 } 270 271 abort(); 272 273#undef HANDLE 274} 275 276static enum arg_class 277allocate_sse(struct fetch_context *context, struct value *valuep, 278 size_t sz, size_t offset, enum reg_pool pool) 279{ 280 size_t num_regs = 0; 281 switch (pool) { 282 case POOL_FUNCALL: 283 num_regs = 8; 284 case POOL_SYSCALL: 285 break; 286 case POOL_RETVAL: 287 num_regs = 2; 288 } 289 290 if (context->freg >= num_regs) { 291 /* We shouldn't see overflow for RETVAL or SYSCALL 292 * pool. */ 293 assert(pool == POOL_FUNCALL); 294 allocate_stack_slot(context, valuep, sz, offset, 8); 295 return CLASS_MEMORY; 296 } else { 297 copy_sse_register(context, valuep, 0, sz, offset); 298 return CLASS_SSE; 299 } 300} 301 302/* This allocates registers or stack space for another argument of the 303 * class CLS. */ 304static enum arg_class 305allocate_class(enum arg_class cls, struct fetch_context *context, 306 struct value *valuep, size_t sz, size_t offset, enum reg_pool pool) 307{ 308 switch (cls) { 309 case CLASS_MEMORY: 310 allocate_stack_slot(context, valuep, sz, offset, 8); 311 case CLASS_NO: 312 return cls; 313 314 case CLASS_INTEGER: 315 return allocate_integer(context, valuep, sz, offset, pool); 316 317 case CLASS_SSE: 318 return allocate_sse(context, valuep, sz, offset, pool); 319 320 case CLASS_X87: 321 return allocate_x87(context, valuep, sz, offset, pool, 8); 322 } 323 abort(); 324} 325 326static ssize_t 327classify(struct Process *proc, struct fetch_context *context, 328 struct arg_type_info *info, struct value *valuep, enum arg_class classes[], 329 size_t sz, size_t eightbytes); 330 331/* This classifies one eightbyte part of an array or struct. */ 332static ssize_t 333classify_eightbyte(struct Process *proc, struct fetch_context *context, 334 struct arg_type_info *info, struct value *valuep, 335 enum arg_class *classp, size_t start, size_t end, 336 struct arg_type_info *(*getter)(struct arg_type_info *, 337 size_t)) 338{ 339 size_t i; 340 enum arg_class cls = CLASS_NO; 341 for (i = start; i < end; ++i) { 342 enum arg_class cls2; 343 struct arg_type_info *info2 = getter(info, i); 344 size_t sz = type_sizeof(proc, info2); 345 if (sz == (size_t)-1) 346 return -1; 347 if (classify(proc, context, info2, valuep, &cls2, sz, 1) < 0) 348 return -1; 349 350 if (cls == CLASS_NO) 351 cls = cls2; 352 else if (cls2 == CLASS_NO || cls == cls2) 353 ; 354 else if (cls == CLASS_MEMORY || cls2 == CLASS_MEMORY) 355 cls = CLASS_MEMORY; 356 else if (cls == CLASS_INTEGER || cls2 == CLASS_INTEGER) 357 cls = CLASS_INTEGER; 358 else 359 cls = CLASS_SSE; 360 } 361 362 *classp = cls; 363 return 1; 364} 365 366/* This classifies small arrays and structs. */ 367static ssize_t 368classify_eightbytes(struct Process *proc, struct fetch_context *context, 369 struct arg_type_info *info, struct value *valuep, 370 enum arg_class classes[], size_t elements, 371 size_t eightbytes, 372 struct arg_type_info *(*getter)(struct arg_type_info *, 373 size_t)) 374{ 375 if (eightbytes > 1) { 376 /* Where the second eightbyte starts. Number of the 377 * first element in the structure that belongs to the 378 * second eightbyte. */ 379 size_t start_2nd = 0; 380 size_t i; 381 for (i = 0; i < elements; ++i) 382 if (type_offsetof(proc, info, i) >= 8) { 383 start_2nd = i; 384 break; 385 } 386 387 enum arg_class cls1, cls2; 388 if (classify_eightbyte(proc, context, info, valuep, &cls1, 389 0, start_2nd, getter) < 0 390 || classify_eightbyte(proc, context, info, valuep, &cls2, 391 start_2nd, elements, getter) < 0) 392 return -1; 393 394 if (cls1 == CLASS_MEMORY || cls2 == CLASS_MEMORY) { 395 classes[0] = CLASS_MEMORY; 396 return 1; 397 } 398 399 classes[0] = cls1; 400 classes[1] = cls2; 401 return 2; 402 } 403 404 return classify_eightbyte(proc, context, info, valuep, classes, 405 0, elements, getter); 406} 407 408static struct arg_type_info * 409get_array_field(struct arg_type_info *info, size_t emt) 410{ 411 return info->u.array_info.elt_type; 412} 413 414static ssize_t 415classify(struct Process *proc, struct fetch_context *context, 416 struct arg_type_info *info, struct value *valuep, enum arg_class classes[], 417 size_t sz, size_t eightbytes) 418{ 419 switch (info->type) { 420 case ARGTYPE_VOID: 421 return 0; 422 423 case ARGTYPE_CHAR: 424 case ARGTYPE_SHORT: 425 case ARGTYPE_USHORT: 426 case ARGTYPE_INT: 427 case ARGTYPE_UINT: 428 case ARGTYPE_LONG: 429 case ARGTYPE_ULONG: 430 431 case ARGTYPE_POINTER: 432 /* and LONGLONG */ 433 /* CLASS_INTEGER */ 434 classes[0] = CLASS_INTEGER; 435 return 1; 436 437 case ARGTYPE_FLOAT: 438 case ARGTYPE_DOUBLE: 439 /* and DECIMAL, and _m64 */ 440 classes[0] = CLASS_SSE; 441 return 1; 442 443 case ARGTYPE_ARRAY: 444 /* N.B. this cannot be top-level array, those decay to 445 * pointers. Therefore, it must be inside structure 446 * that's at most 2 eightbytes long. */ 447 448 /* Structures with flexible array members can't be 449 * passed by value. */ 450 assert(expr_is_compile_constant(info->u.array_info.length)); 451 452 long l; 453 if (expr_eval_constant(info->u.array_info.length, &l) < 0) 454 return -1; 455 456 return classify_eightbytes(proc, context, info, valuep, classes, 457 (size_t)l, eightbytes, 458 get_array_field); 459 460 case ARGTYPE_STRUCT: 461 /* N.B. "big" structs are dealt with in the 462 * caller. */ 463 return classify_eightbytes(proc, context, info, valuep, classes, 464 type_struct_size(info), 465 eightbytes, type_struct_get); 466 } 467 abort(); 468} 469 470static ssize_t 471pass_by_reference(struct value *valuep, enum arg_class classes[]) 472{ 473 if (valuep != NULL && value_pass_by_reference(valuep) < 0) 474 return -1; 475 classes[0] = CLASS_INTEGER; 476 return 1; 477} 478 479static ssize_t 480classify_argument(struct Process *proc, struct fetch_context *context, 481 struct arg_type_info *info, struct value *valuep, 482 enum arg_class classes[], size_t *sizep) 483{ 484 size_t sz = type_sizeof(proc, info); 485 if (sz == (size_t)-1) 486 return -1; 487 *sizep = sz; 488 489 size_t eightbytes = (sz + 7) / 8; /* Round up. */ 490 491 /* Arrays decay into pointers. */ 492 assert(info->type != ARGTYPE_ARRAY); 493 494 if (info->type == ARGTYPE_STRUCT) { 495 if (eightbytes > 2 || contains_unaligned_fields(info)) { 496 classes[0] = CLASS_MEMORY; 497 return 1; 498 } 499 500 if (has_nontrivial_ctor_dtor(info)) 501 return pass_by_reference(valuep, classes); 502 } 503 504 return classify(proc, context, info, valuep, classes, sz, eightbytes); 505} 506 507static int 508fetch_register_banks(struct Process *proc, struct fetch_context *context, 509 int floating) 510{ 511 if (ptrace(PTRACE_GETREGS, proc->pid, 0, &context->iregs) < 0) 512 return -1; 513 context->ireg = 0; 514 515 if (floating) { 516 if (ptrace(PTRACE_GETFPREGS, proc->pid, 517 0, &context->fpregs) < 0) 518 return -1; 519 context->freg = 0; 520 } else { 521 context->freg = -1; 522 } 523 524 return 0; 525} 526 527static int 528arch_fetch_arg_next_32(struct fetch_context *context, enum tof type, 529 struct Process *proc, struct arg_type_info *info, 530 struct value *valuep) 531{ 532 size_t sz = type_sizeof(proc, info); 533 if (sz == (size_t)-1) 534 return -1; 535 536 allocate_stack_slot(context, valuep, sz, 0, 4); 537 538 return 0; 539} 540 541static int 542arch_fetch_retval_32(struct fetch_context *context, enum tof type, 543 struct Process *proc, struct arg_type_info *info, 544 struct value *valuep) 545{ 546 if (fetch_register_banks(proc, context, type == LT_TOF_FUNCTIONR) < 0) 547 return -1; 548 549 struct value *retval = &context->u.ix86.retval; 550 if (retval->type != NULL) { 551 /* Struct return value was extracted when in fetch 552 * init. */ 553 memcpy(valuep, &context->u.ix86.retval, sizeof(*valuep)); 554 return 0; 555 } 556 557 size_t sz = type_sizeof(proc, info); 558 if (sz == (size_t)-1) 559 return -1; 560 if (value_reserve(valuep, sz) == NULL) 561 return -1; 562 563 switch (info->type) { 564 enum arg_class cls; 565 case ARGTYPE_VOID: 566 return 0; 567 568 case ARGTYPE_INT: 569 case ARGTYPE_UINT: 570 case ARGTYPE_LONG: 571 case ARGTYPE_ULONG: 572 case ARGTYPE_CHAR: 573 case ARGTYPE_SHORT: 574 case ARGTYPE_USHORT: 575 case ARGTYPE_POINTER: 576 cls = allocate_integer(context, valuep, sz, 0, POOL_RETVAL); 577 assert(cls == CLASS_INTEGER); 578 return 0; 579 580 case ARGTYPE_FLOAT: 581 case ARGTYPE_DOUBLE: 582 cls = allocate_x87(context, valuep, sz, 0, POOL_RETVAL, 4); 583 assert(cls == CLASS_X87); 584 return 0; 585 586 case ARGTYPE_ARRAY: 587 case ARGTYPE_STRUCT: /* Handled above. */ 588 assert(!"Unexpected i386 retval type!"); 589 abort(); 590 } 591 592 abort(); 593} 594 595static arch_addr_t 596fetch_stack_pointer(struct fetch_context *context) 597{ 598 arch_addr_t sp; 599#ifdef __x86_64__ 600 sp = (arch_addr_t)context->iregs.rsp; 601#else 602 sp = (arch_addr_t)context->iregs.esp; 603#endif 604 return sp; 605} 606 607struct fetch_context * 608arch_fetch_arg_init_32(struct fetch_context *context, 609 enum tof type, struct Process *proc, 610 struct arg_type_info *ret_info) 611{ 612 context->stack_pointer = fetch_stack_pointer(context) + 4; 613 614 size_t sz = type_sizeof(proc, ret_info); 615 if (sz == (size_t)-1) 616 return NULL; 617 618 struct value *retval = &context->u.ix86.retval; 619 if (ret_info->type == ARGTYPE_STRUCT) { 620 value_init(retval, proc, NULL, ret_info, 0); 621 622 enum arg_class dummy[2]; 623 if (pass_by_reference(retval, dummy) < 0) 624 return NULL; 625 allocate_stack_slot(context, retval, 4, 0, 4); 626 627 } else { 628 value_init_detached(retval, NULL, NULL, 0); 629 } 630 631 return context; 632} 633 634struct fetch_context * 635arch_fetch_arg_init_64(struct fetch_context *ctx, enum tof type, 636 struct Process *proc, struct arg_type_info *ret_info) 637{ 638 /* The first stack slot holds a return address. */ 639 ctx->stack_pointer = fetch_stack_pointer(ctx) + 8; 640 641 size_t size; 642 ctx->u.x86_64.num_ret_classes 643 = classify_argument(proc, ctx, ret_info, NULL, 644 ctx->u.x86_64.ret_classes, &size); 645 if (ctx->u.x86_64.num_ret_classes == -1) 646 return NULL; 647 648 /* If the class is MEMORY, then the first argument is a hidden 649 * pointer to the allocated storage. */ 650 if (ctx->u.x86_64.num_ret_classes > 0 651 && ctx->u.x86_64.ret_classes[0] == CLASS_MEMORY) { 652 /* MEMORY should be the sole class. */ 653 assert(ctx->u.x86_64.num_ret_classes == 1); 654 allocate_integer(ctx, NULL, size, 0, POOL_FUNCALL); 655 } 656 657 return ctx; 658} 659 660struct fetch_context * 661arch_fetch_arg_init(enum tof type, struct Process *proc, 662 struct arg_type_info *ret_info) 663{ 664 struct fetch_context *ctx = malloc(sizeof(*ctx)); 665 if (ctx == NULL) 666 return NULL; 667 668 assert(type != LT_TOF_FUNCTIONR 669 && type != LT_TOF_SYSCALLR); 670 if (fetch_register_banks(proc, ctx, type == LT_TOF_FUNCTION) < 0) { 671 fail: 672 free(ctx); 673 return NULL; 674 } 675 676 struct fetch_context *ret; 677 if (proc->e_machine == EM_386) 678 ret = arch_fetch_arg_init_32(ctx, type, proc, ret_info); 679 else 680 ret = arch_fetch_arg_init_64(ctx, type, proc, ret_info); 681 if (ret == NULL) 682 goto fail; 683 return ret; 684} 685 686struct fetch_context * 687arch_fetch_arg_clone(struct Process *proc, struct fetch_context *context) 688{ 689 struct fetch_context *ret = malloc(sizeof(*ret)); 690 if (ret == NULL) 691 return NULL; 692 return memcpy(ret, context, sizeof(*ret)); 693} 694 695static int 696arch_fetch_pool_arg_next(struct fetch_context *context, enum tof type, 697 struct Process *proc, struct arg_type_info *info, 698 struct value *valuep, enum reg_pool pool) 699{ 700 enum arg_class classes[2]; 701 size_t sz, sz1; 702 ssize_t i; 703 ssize_t nclasses = classify_argument(proc, context, info, valuep, 704 classes, &sz); 705 if (nclasses == -1) 706 return -1; 707 if (value_reserve(valuep, sz) == NULL) 708 return -1; 709 710 /* If there are no registers available for any eightbyte of an 711 * argument, the whole argument is passed on the stack. If 712 * registers have already been assigned for some eightbytes of 713 * such an argument, the assignments get reverted. */ 714 struct fetch_context tmp_context = *context; 715 int revert; 716 if (nclasses == 1) { 717 revert = allocate_class(classes[0], &tmp_context, 718 valuep, sz, 0, pool) != classes[0]; 719 } else { 720 revert = 0; 721 for (i = 0; i < nclasses; ++i) { 722 sz1 = (size_t)(8 * (i + 1)) > sz ? sz - 8 * i : 8; 723 if (allocate_class(classes[i], &tmp_context, valuep, 724 sz1, 8 * i, pool) != classes[i]) 725 revert = 1; 726 } 727 } 728 729 if (nclasses > 1 && revert) 730 allocate_class(CLASS_MEMORY, context, valuep, sz, 0, pool); 731 else 732 *context = tmp_context; /* Commit. */ 733 734 return 0; 735} 736 737int 738arch_fetch_fun_retval(struct fetch_context *context, enum tof type, 739 struct Process *proc, struct arg_type_info *info, 740 struct value *valuep) 741{ 742 assert(type != LT_TOF_FUNCTION 743 && type != LT_TOF_SYSCALL); 744 if (value_reserve(valuep, 8 * context->u.x86_64.num_ret_classes) == NULL 745 || fetch_register_banks(proc, context, 746 type == LT_TOF_FUNCTIONR) < 0) 747 return -1; 748 749 if (context->u.x86_64.num_ret_classes == 1 750 && context->u.x86_64.ret_classes[0] == CLASS_MEMORY) 751 pass_by_reference(valuep, context->u.x86_64.ret_classes); 752 753 size_t sz = type_sizeof(proc, valuep->type); 754 if (sz == (size_t)-1) 755 return -1; 756 757 ssize_t i; 758 size_t sz1 = context->u.x86_64.num_ret_classes == 1 ? sz : 8; 759 for (i = 0; i < context->u.x86_64.num_ret_classes; ++i) { 760 enum arg_class cls 761 = allocate_class(context->u.x86_64.ret_classes[i], 762 context, valuep, sz1, 763 8 * i, POOL_RETVAL); 764 assert(cls == context->u.x86_64.ret_classes[i]); 765 } 766 return 0; 767} 768 769int 770arch_fetch_arg_next(struct fetch_context *context, enum tof type, 771 struct Process *proc, struct arg_type_info *info, 772 struct value *valuep) 773{ 774 if (proc->e_machine == EM_386) 775 return arch_fetch_arg_next_32(context, type, proc, 776 info, valuep); 777 778 switch (type) { 779 case LT_TOF_FUNCTION: 780 case LT_TOF_FUNCTIONR: 781 return arch_fetch_pool_arg_next(context, type, proc, 782 info, valuep, POOL_FUNCALL); 783 784 case LT_TOF_SYSCALL: 785 case LT_TOF_SYSCALLR: 786 return arch_fetch_pool_arg_next(context, type, proc, 787 info, valuep, POOL_SYSCALL); 788 } 789 790 abort(); 791} 792 793int 794arch_fetch_retval(struct fetch_context *context, enum tof type, 795 struct Process *proc, struct arg_type_info *info, 796 struct value *valuep) 797{ 798 if (proc->e_machine == EM_386) 799 return arch_fetch_retval_32(context, type, proc, info, valuep); 800 801 return arch_fetch_fun_retval(context, type, proc, info, valuep); 802} 803 804void 805arch_fetch_arg_done(struct fetch_context *context) 806{ 807 if (context != NULL) 808 free(context); 809} 810