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