1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
|
/****************************************************************
* *
* Copyright 2003, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
* under a license. If you do not know the terms of *
* the license, please stop and do not read further. *
* *
****************************************************************/
#include "mdef.h"
#include "gtm_string.h"
#include "urx.h"
#include <rtnhdr.h>
#include "stack_frame.h"
#include "op.h"
#include <auto_zlink.h>
GBLREF unsigned char *obpt; /* output buffer index */
GBLREF stack_frame *frame_pointer;
IA64_ONLY(GBLREF uint8 imm14;)
IA64_ONLY(GBLREF char asm_mode;)
/* Due to the complex instruction set of x86_64, we require a function to implement the macro VALID_CALLING_SEQUENCE
* and this function will calculate both the offsets (rtnhdr & labaddr) and store them into these global variables.
*/
#if defined(__x86_64__) || defined(__MVS__) || defined(Linux390)
GBLDEF int4 rtnhdr_off;
GBLDEF int4 labaddr_off;
#endif
error_def (ERR_LABELUNKNOWN);
error_def (ERR_ROUTINEUNKNOWN);
rhdtyp *auto_zlink(mach_inst *pc, lnr_tabent ***line)
{
lnk_tabent *A_rtnhdr;
lnk_tabent *A_labaddr;
mstr rname;
mident_fixed rname_buff;
mval rtn;
rhdtyp *rhead;
urx_rtnref *rtnurx;
# ifdef USHBIN_SUPPORTED
/* With the current autorelink multi-opcode call (OP_RHD_EXT and OP_LAB_EXT prior to actual call), auto_zlink()
* isn't really at all used but this is likely to change in the next release which streamlines some of this so
* for now, this routine is not being nixed.
*/
USHBIN_ONLY(assertpro(FALSE));
# else
/* (ASSUMPTION)
* The instructions immediately preceding the current mpc form a transfer table call.
* There will be two arguments to this call:
* the address of a routine header and
* the address of a pointer to a value which is the offset from the beginning of the routine header
* to the address of the first instruction to be executed in the routine to be called, as
* specified by the [label][+offset] field (or the beginning of the routine if label and
* offset are not specified)
* We compute the linkage table offsets of both parameters by disassembling the load instructions that were
* generated to load arguments. The entire instruction sequence is platform dependent (see auto_zlink_sp.h).
*
* N.B., the instruction sequence above occurs in compiled object modules; in direct mode, the argument
* registers are loaded via "load" instructions. However, this routine should never be invoked from direct
* mode because the applicable routine should have been ZLINK'ed by prior calls to op_labaddr and op_rhdaddr.
*/
NON_IA64_ONLY(assertpro(VALID_CALLING_SEQUENCE(pc)));
/* Calling sequence O.K.; get address(address(routine header)) and address(address(label offset)). */
# ifdef __ia64 /* __ia64 */
{
uint8 imm;
int8 *buf2, i;
ia64_bundle bundle;
uint8 dummy, dummy2, dummy1;
int isMovl = 0;
RTNHDR_PV_OFF(pc,imm);
A_rtnhdr = (lnk_tabent *)(imm + frame_pointer->ctxt);
dummy1 = dummy; /* For silly compiler warning */
LABADDR_PV_OFF(pc, imm);
A_labaddr = (lnk_tabent *)(imm + frame_pointer->ctxt);
}
# endif /* __ia64 */
NON_IA64_ONLY(A_rtnhdr = (lnk_tabent *)(RTNHDR_PV_OFF(pc) + frame_pointer->ctxt);)
NON_IA64_ONLY(A_labaddr = (lnk_tabent *)(LABADDR_PV_OFF(pc) + frame_pointer->ctxt);)
if (azl_geturxrtn((char *)A_rtnhdr, &rname, &rtnurx))
{
assert(rname.len <= MAX_MIDENT_LEN);
assert(0 != rname.addr);
/* Copy rname into local storage because azl_geturxrtn sets rname.addr to an address that is
* free'd during op_zlink and before the call to find_rtn_hdr.
*/
memcpy(rname_buff.c, rname.addr, rname.len);
rname.addr = rname_buff.c;
assert(0 != rtnurx);
assert(azl_geturxlab((char *)A_labaddr, rtnurx));
assert(0 == find_rtn_hdr(&rname));
rtn.mvtype = MV_STR;
rtn.str.len = rname.len;
rtn.str.addr = rname.addr;
op_zlink(&rtn, 0);
if (0 != (rhead = find_rtn_hdr(&rname)))
{ /* Pull the linkage table reference out and return it to caller */
*line = (lnr_tabent **)(A_labaddr->ext_ref);
if (0 == *line)
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_LABELUNKNOWN);
return rhead;
}
}
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_ROUTINEUNKNOWN);
# endif /* ifdef USHBIN_SUPPORTED */
return NULL; /* Compiler happiness phase */
}
|