fetch.c revision 5b5c256d0e9076e745908a43acc46353265a5608
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 int 415flatten_structure(struct arg_type_info *flattened, struct arg_type_info *info) 416{ 417 size_t i; 418 for (i = 0; i < type_struct_size(info); ++i) { 419 struct arg_type_info *field = type_struct_get(info, i); 420 assert(field != NULL); 421 switch (field->type) { 422 case ARGTYPE_STRUCT: 423 if (flatten_structure(flattened, field) < 0) 424 return -1; 425 break; 426 427 default: 428 if (type_struct_add(flattened, field, 0) < 0) 429 return -1; 430 } 431 } 432 return 0; 433} 434 435static ssize_t 436classify(struct Process *proc, struct fetch_context *context, 437 struct arg_type_info *info, struct value *valuep, enum arg_class classes[], 438 size_t sz, size_t eightbytes) 439{ 440 switch (info->type) { 441 struct arg_type_info flattened; 442 case ARGTYPE_VOID: 443 return 0; 444 445 case ARGTYPE_CHAR: 446 case ARGTYPE_SHORT: 447 case ARGTYPE_USHORT: 448 case ARGTYPE_INT: 449 case ARGTYPE_UINT: 450 case ARGTYPE_LONG: 451 case ARGTYPE_ULONG: 452 453 case ARGTYPE_POINTER: 454 /* and LONGLONG */ 455 /* CLASS_INTEGER */ 456 classes[0] = CLASS_INTEGER; 457 return 1; 458 459 case ARGTYPE_FLOAT: 460 case ARGTYPE_DOUBLE: 461 /* and DECIMAL, and _m64 */ 462 classes[0] = CLASS_SSE; 463 return 1; 464 465 case ARGTYPE_ARRAY: 466 /* N.B. this cannot be top-level array, those decay to 467 * pointers. Therefore, it must be inside structure 468 * that's at most 2 eightbytes long. */ 469 470 /* Structures with flexible array members can't be 471 * passed by value. */ 472 assert(expr_is_compile_constant(info->u.array_info.length)); 473 474 long l; 475 if (expr_eval_constant(info->u.array_info.length, &l) < 0) 476 return -1; 477 478 return classify_eightbytes(proc, context, info, valuep, classes, 479 (size_t)l, eightbytes, 480 get_array_field); 481 482 case ARGTYPE_STRUCT: 483 /* N.B. "big" structs are dealt with in the caller. 484 * 485 * First, we need to flatten the structure. In 486 * struct(float,struct(float,float)), first two floats 487 * both belong to the same eightbyte. */ 488 type_init_struct(&flattened); 489 490 ssize_t ret; 491 if (flatten_structure(&flattened, info) < 0) { 492 ret = -1; 493 goto done; 494 } 495 ret = classify_eightbytes(proc, context, &flattened, 496 valuep, classes, 497 type_struct_size(&flattened), 498 eightbytes, type_struct_get); 499 done: 500 type_destroy(&flattened); 501 return ret; 502 503 default: 504 /* Unsupported type. */ 505 assert(info->type != info->type); 506 abort(); 507 } 508 abort(); 509} 510 511static ssize_t 512pass_by_reference(struct value *valuep, enum arg_class classes[]) 513{ 514 if (valuep != NULL && value_pass_by_reference(valuep) < 0) 515 return -1; 516 classes[0] = CLASS_INTEGER; 517 return 1; 518} 519 520static ssize_t 521classify_argument(struct Process *proc, struct fetch_context *context, 522 struct arg_type_info *info, struct value *valuep, 523 enum arg_class classes[], size_t *sizep) 524{ 525 size_t sz = type_sizeof(proc, info); 526 if (sz == (size_t)-1) 527 return -1; 528 *sizep = sz; 529 530 size_t eightbytes = (sz + 7) / 8; /* Round up. */ 531 532 /* Arrays decay into pointers. */ 533 assert(info->type != ARGTYPE_ARRAY); 534 535 if (info->type == ARGTYPE_STRUCT) { 536 if (eightbytes > 2 || contains_unaligned_fields(info)) { 537 classes[0] = CLASS_MEMORY; 538 return 1; 539 } 540 541 if (has_nontrivial_ctor_dtor(info)) 542 return pass_by_reference(valuep, classes); 543 } 544 545 return classify(proc, context, info, valuep, classes, sz, eightbytes); 546} 547 548static int 549fetch_register_banks(struct Process *proc, struct fetch_context *context, 550 int floating) 551{ 552 if (ptrace(PTRACE_GETREGS, proc->pid, 0, &context->iregs) < 0) 553 return -1; 554 context->ireg = 0; 555 556 if (floating) { 557 if (ptrace(PTRACE_GETFPREGS, proc->pid, 558 0, &context->fpregs) < 0) 559 return -1; 560 context->freg = 0; 561 } else { 562 context->freg = -1; 563 } 564 565 return 0; 566} 567 568static int 569arch_fetch_arg_next_32(struct fetch_context *context, enum tof type, 570 struct Process *proc, struct arg_type_info *info, 571 struct value *valuep) 572{ 573 size_t sz = type_sizeof(proc, info); 574 if (sz == (size_t)-1) 575 return -1; 576 577 allocate_stack_slot(context, valuep, sz, 0, 4); 578 579 return 0; 580} 581 582static int 583arch_fetch_retval_32(struct fetch_context *context, enum tof type, 584 struct Process *proc, struct arg_type_info *info, 585 struct value *valuep) 586{ 587 if (fetch_register_banks(proc, context, type == LT_TOF_FUNCTIONR) < 0) 588 return -1; 589 590 struct value *retval = &context->u.ix86.retval; 591 if (retval->type != NULL) { 592 /* Struct return value was extracted when in fetch 593 * init. */ 594 memcpy(valuep, &context->u.ix86.retval, sizeof(*valuep)); 595 return 0; 596 } 597 598 size_t sz = type_sizeof(proc, info); 599 if (sz == (size_t)-1) 600 return -1; 601 if (value_reserve(valuep, sz) == NULL) 602 return -1; 603 604 switch (info->type) { 605 enum arg_class cls; 606 case ARGTYPE_VOID: 607 return 0; 608 609 case ARGTYPE_INT: 610 case ARGTYPE_UINT: 611 case ARGTYPE_LONG: 612 case ARGTYPE_ULONG: 613 case ARGTYPE_CHAR: 614 case ARGTYPE_SHORT: 615 case ARGTYPE_USHORT: 616 case ARGTYPE_POINTER: 617 cls = allocate_integer(context, valuep, sz, 0, POOL_RETVAL); 618 assert(cls == CLASS_INTEGER); 619 return 0; 620 621 case ARGTYPE_FLOAT: 622 case ARGTYPE_DOUBLE: 623 cls = allocate_x87(context, valuep, sz, 0, POOL_RETVAL, 4); 624 assert(cls == CLASS_X87); 625 return 0; 626 627 case ARGTYPE_STRUCT: /* Handled above. */ 628 default: 629 assert(!"Unexpected i386 retval type!"); 630 abort(); 631 } 632 633 abort(); 634} 635 636static arch_addr_t 637fetch_stack_pointer(struct fetch_context *context) 638{ 639 arch_addr_t sp; 640#ifdef __x86_64__ 641 sp = (arch_addr_t)context->iregs.rsp; 642#else 643 sp = (arch_addr_t)context->iregs.esp; 644#endif 645 return sp; 646} 647 648struct fetch_context * 649arch_fetch_arg_init_32(struct fetch_context *context, 650 enum tof type, struct Process *proc, 651 struct arg_type_info *ret_info) 652{ 653 context->stack_pointer = fetch_stack_pointer(context) + 4; 654 655 size_t sz = type_sizeof(proc, ret_info); 656 if (sz == (size_t)-1) 657 return NULL; 658 659 struct value *retval = &context->u.ix86.retval; 660 if (ret_info->type == ARGTYPE_STRUCT) { 661 value_init(retval, proc, NULL, ret_info, 0); 662 663 enum arg_class dummy[2]; 664 if (pass_by_reference(retval, dummy) < 0) 665 return NULL; 666 allocate_stack_slot(context, retval, 4, 0, 4); 667 668 } else { 669 value_init_detached(retval, NULL, NULL, 0); 670 } 671 672 return context; 673} 674 675struct fetch_context * 676arch_fetch_arg_init_64(struct fetch_context *ctx, enum tof type, 677 struct Process *proc, struct arg_type_info *ret_info) 678{ 679 /* The first stack slot holds a return address. */ 680 ctx->stack_pointer = fetch_stack_pointer(ctx) + 8; 681 682 size_t size; 683 ctx->u.x86_64.num_ret_classes 684 = classify_argument(proc, ctx, ret_info, NULL, 685 ctx->u.x86_64.ret_classes, &size); 686 if (ctx->u.x86_64.num_ret_classes == -1) 687 return NULL; 688 689 /* If the class is MEMORY, then the first argument is a hidden 690 * pointer to the allocated storage. */ 691 if (ctx->u.x86_64.num_ret_classes > 0 692 && ctx->u.x86_64.ret_classes[0] == CLASS_MEMORY) { 693 /* MEMORY should be the sole class. */ 694 assert(ctx->u.x86_64.num_ret_classes == 1); 695 allocate_integer(ctx, NULL, size, 0, POOL_FUNCALL); 696 } 697 698 return ctx; 699} 700 701struct fetch_context * 702arch_fetch_arg_init(enum tof type, struct Process *proc, 703 struct arg_type_info *ret_info) 704{ 705 struct fetch_context *ctx = malloc(sizeof(*ctx)); 706 if (ctx == NULL) 707 return NULL; 708 709 assert(type != LT_TOF_FUNCTIONR 710 && type != LT_TOF_SYSCALLR); 711 if (fetch_register_banks(proc, ctx, type == LT_TOF_FUNCTION) < 0) { 712 fail: 713 free(ctx); 714 return NULL; 715 } 716 717 struct fetch_context *ret; 718 if (proc->e_machine == EM_386) 719 ret = arch_fetch_arg_init_32(ctx, type, proc, ret_info); 720 else 721 ret = arch_fetch_arg_init_64(ctx, type, proc, ret_info); 722 if (ret == NULL) 723 goto fail; 724 return ret; 725} 726 727struct fetch_context * 728arch_fetch_arg_clone(struct Process *proc, struct fetch_context *context) 729{ 730 struct fetch_context *ret = malloc(sizeof(*ret)); 731 if (ret == NULL) 732 return NULL; 733 return memcpy(ret, context, sizeof(*ret)); 734} 735 736static int 737arch_fetch_pool_arg_next(struct fetch_context *context, enum tof type, 738 struct Process *proc, struct arg_type_info *info, 739 struct value *valuep, enum reg_pool pool) 740{ 741 enum arg_class classes[2]; 742 size_t sz, sz1; 743 ssize_t i; 744 ssize_t nclasses = classify_argument(proc, context, info, valuep, 745 classes, &sz); 746 if (nclasses == -1) 747 return -1; 748 if (value_reserve(valuep, sz) == NULL) 749 return -1; 750 751 /* If there are no registers available for any eightbyte of an 752 * argument, the whole argument is passed on the stack. If 753 * registers have already been assigned for some eightbytes of 754 * such an argument, the assignments get reverted. */ 755 struct fetch_context tmp_context = *context; 756 int revert; 757 if (nclasses == 1) { 758 revert = allocate_class(classes[0], &tmp_context, 759 valuep, sz, 0, pool) != classes[0]; 760 } else { 761 revert = 0; 762 for (i = 0; i < nclasses; ++i) { 763 sz1 = (size_t)(8 * (i + 1)) > sz ? sz - 8 * i : 8; 764 if (allocate_class(classes[i], &tmp_context, valuep, 765 sz1, 8 * i, pool) != classes[i]) 766 revert = 1; 767 } 768 } 769 770 if (nclasses > 1 && revert) 771 allocate_class(CLASS_MEMORY, context, valuep, sz, 0, pool); 772 else 773 *context = tmp_context; /* Commit. */ 774 775 return 0; 776} 777 778int 779arch_fetch_fun_retval(struct fetch_context *context, enum tof type, 780 struct Process *proc, struct arg_type_info *info, 781 struct value *valuep) 782{ 783 assert(type != LT_TOF_FUNCTION 784 && type != LT_TOF_SYSCALL); 785 if (value_reserve(valuep, 8 * context->u.x86_64.num_ret_classes) == NULL 786 || fetch_register_banks(proc, context, 787 type == LT_TOF_FUNCTIONR) < 0) 788 return -1; 789 790 if (context->u.x86_64.num_ret_classes == 1 791 && context->u.x86_64.ret_classes[0] == CLASS_MEMORY) 792 pass_by_reference(valuep, context->u.x86_64.ret_classes); 793 794 size_t sz = type_sizeof(proc, valuep->type); 795 if (sz == (size_t)-1) 796 return -1; 797 798 ssize_t i; 799 size_t sz1 = context->u.x86_64.num_ret_classes == 1 ? sz : 8; 800 for (i = 0; i < context->u.x86_64.num_ret_classes; ++i) { 801 enum arg_class cls 802 = allocate_class(context->u.x86_64.ret_classes[i], 803 context, valuep, sz1, 804 8 * i, POOL_RETVAL); 805 assert(cls == context->u.x86_64.ret_classes[i]); 806 } 807 return 0; 808} 809 810int 811arch_fetch_arg_next(struct fetch_context *context, enum tof type, 812 struct Process *proc, struct arg_type_info *info, 813 struct value *valuep) 814{ 815 if (proc->e_machine == EM_386) 816 return arch_fetch_arg_next_32(context, type, proc, 817 info, valuep); 818 819 switch (type) { 820 case LT_TOF_FUNCTION: 821 case LT_TOF_FUNCTIONR: 822 return arch_fetch_pool_arg_next(context, type, proc, 823 info, valuep, POOL_FUNCALL); 824 825 case LT_TOF_SYSCALL: 826 case LT_TOF_SYSCALLR: 827 return arch_fetch_pool_arg_next(context, type, proc, 828 info, valuep, POOL_SYSCALL); 829 } 830 831 abort(); 832} 833 834int 835arch_fetch_retval(struct fetch_context *context, enum tof type, 836 struct Process *proc, struct arg_type_info *info, 837 struct value *valuep) 838{ 839 if (proc->e_machine == EM_386) 840 return arch_fetch_retval_32(context, type, proc, info, valuep); 841 842 return arch_fetch_fun_retval(context, type, proc, info, valuep); 843} 844 845void 846arch_fetch_arg_done(struct fetch_context *context) 847{ 848 if (context != NULL) 849 free(context); 850} 851