* Send a "call" trampoline metadata. */
| 2144 | * Send a "call" trampoline metadata. |
| 2145 | */ |
| 2146 | void e9tool::sendCallMetadata(FILE *out, const char *name, const ELF *elf, |
| 2147 | const Call &call, const std::vector<Argument> &args, |
| 2148 | intptr_t id, const std::vector<Instr> &Is, size_t i, const InstrInfo *I) |
| 2149 | { |
| 2150 | // Load arguments. |
| 2151 | bool sysv = true; |
| 2152 | switch (elf->type) |
| 2153 | { |
| 2154 | case BINARY_TYPE_PE_EXE: case BINARY_TYPE_PE_DLL: |
| 2155 | sysv = false; |
| 2156 | break; |
| 2157 | default: |
| 2158 | break; |
| 2159 | } |
| 2160 | |
| 2161 | name++; |
| 2162 | sendDefinitionHeader(out, name, "ARGS"); |
| 2163 | int argno = 0; |
| 2164 | bool before = (call.pos == POS_BEFORE); |
| 2165 | bool pic = (getELFType(elf) != BINARY_TYPE_ELF_EXE); |
| 2166 | CallInfo info(sysv, (call.abi == ABI_CLEAN), call.state, |
| 2167 | (call.jmp != JUMP_NONE), args.size(), before, pic); |
| 2168 | TypeSig sig = TYPESIG_EMPTY; |
| 2169 | if (args.size() != call.nargs) |
| 2170 | error("failed to emit call metadata; expected %zu arguments, " |
| 2171 | "found %zu", call.nargs, args.size()); |
| 2172 | size_t j = 0; |
| 2173 | for (const auto &arg: args) |
| 2174 | { |
| 2175 | j++; |
| 2176 | int regno = getArgRegIdx(sysv, argno); |
| 2177 | Type t = sendLoadArgumentMetadata(out, info, elf, name, call.pos, Is, |
| 2178 | i, I, id, arg, argno, regno); |
| 2179 | sig = setType(sig, t, argno); |
| 2180 | argno++; |
| 2181 | } |
| 2182 | argno = 0; |
| 2183 | int32_t rsp_args_offset = 0; |
| 2184 | for (int argno = (int)args.size()-1; argno >= 0; argno--) |
| 2185 | { |
| 2186 | // Send stack arguments: |
| 2187 | int regno = getArgRegIdx(sysv, argno); |
| 2188 | switch (regno) |
| 2189 | { |
| 2190 | case R10_IDX: case R11_IDX: |
| 2191 | sendPush(out, info.rsp_offset, before, getReg(regno)); |
| 2192 | rsp_args_offset += sizeof(int64_t); |
| 2193 | break; |
| 2194 | } |
| 2195 | } |
| 2196 | for (int regno = 0; call.abi == ABI_NAKED && regno < RMAX_IDX; regno++) |
| 2197 | { |
| 2198 | Register reg = getReg(regno); |
| 2199 | if (!info.isCallerSave(reg) && info.isClobbered(reg)) |
| 2200 | { |
| 2201 | // Restore clobbered callee-save register: |
| 2202 | int32_t reg_offset = rsp_args_offset; |
| 2203 | reg_offset += info.getOffset(reg); |
nothing calls this directly
no test coverage detected