this repo has no description
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Initial code of 32in64 stub producer

+363
+9
src/dyld/stubgen/produce_stubs_example.h
··· 1 + 2 + void* test_function(void* arg1, int arg2, long long arg3); 3 + const char* library_name = "libpulse.so.5"; 4 + 5 + void produce_stubs() 6 + { 7 + STUBIFY(test_function); 8 + } 9 +
+354
src/dyld/stubgen/stubgen32.cpp
··· 1 + #include <functional> 2 + #include <stdint.h> 3 + #include <iostream> 4 + #include <type_traits> 5 + #include <stdexcept> 6 + #include <vector> 7 + #include <string> 8 + 9 + struct AssemblyString 10 + { 11 + std::string name; 12 + std::string value; 13 + }; 14 + static std::vector<AssemblyString> _strings; 15 + 16 + template <typename Retval> 17 + void handle_retval() { std::cout << "\t// retval - nop (void or 4-byte integer)\n"; } 18 + 19 + template <> void handle_retval<long long>() 20 + { 21 + std::cout << "\t// retval - 8-byte integer\n" 22 + "\tmovq %rax, %rdx\n" 23 + "\tshrq $32, %rdx\n"; // place upper 32-bits into edx 24 + std::cout << "\t// end retval\n"; 25 + } 26 + template <> void handle_retval<void*>() { handle_retval<long long>(); } 27 + template <> void handle_retval<unsigned long long>() { handle_retval<long long>(); } 28 + 29 + class Context 30 + { 31 + public: 32 + Context(const char* name) 33 + : _name(name) 34 + { 35 + } 36 + 37 + bool has_int_registers_left() const 38 + { 39 + return _int_count < 6; 40 + } 41 + 42 + const char* next_int_register(bool _32bit = false) 43 + { 44 + if (!has_int_registers_left()) 45 + throw std::logic_error("No registers left"); 46 + 47 + const char* ARGUMENT_REGS[] = { "%rdi", "%rsi", "%rdx", "%rcx", "%r8", "%r9" }; 48 + const char* ARGUMENT_REGS32[] = { "%edi", "%esi", "%edx", "%ecx", "%r8", "%r9" }; 49 + return _32bit ? ARGUMENT_REGS32[_int_count++] : ARGUMENT_REGS[_int_count++]; 50 + } 51 + 52 + bool has_fp_registers_left() const 53 + { 54 + return _fp_count < 8; 55 + } 56 + 57 + const char* next_fp_register() 58 + { 59 + if (!has_fp_registers_left()) 60 + throw std::logic_error("No fp registers left"); 61 + 62 + const char* FP_ARGUMENT_REGS[] = { "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7" }; 63 + return FP_ARGUMENT_REGS[_fp_count++]; 64 + } 65 + 66 + int esp_advance(int how_much) 67 + { 68 + int rv = _esp_offset; 69 + _esp_offset += how_much; 70 + return rv; 71 + } 72 + 73 + int next_int_stack_offset() 74 + { 75 + if (has_int_registers_left()) 76 + throw std::logic_error("Registers are still left"); 77 + 78 + int offset = (_int_count-6) * 8; 79 + offset += std::max(0, (_fp_count-8) * 16); 80 + 81 + _int_count++; 82 + return offset; 83 + } 84 + 85 + int next_fp_stack_offset() 86 + { 87 + if (has_fp_registers_left()) 88 + throw std::logic_error("FP registers are still left"); 89 + 90 + int offset = (_fp_count-8) * 16; 91 + offset += std::max(0, (_int_count-6) * 8); 92 + 93 + _fp_count++; 94 + return offset; 95 + } 96 + 97 + protected: 98 + const char* _name; 99 + // Next offset in 32-bit argument stack 100 + int _esp_offset = 4; 101 + // How many integer arguments have been converted so far 102 + int _int_count = 0; 103 + // How many floating point arguments have been converted so far 104 + int _fp_count = 0; 105 + }; 106 + 107 + template <typename Argtype> 108 + void copy_argument(Context& ctxt) 109 + { 110 + std::cout << "\tmovl " << ctxt.esp_advance(4) << "(%rsp), " << ctxt.next_int_register(true) << std::endl; 111 + } 112 + 113 + template <> 114 + void copy_argument<long long>(Context& ctxt) 115 + { 116 + std::cout << "\tmovq " << ctxt.esp_advance(8) << "(%rsp), " << ctxt.next_int_register() << std::endl; 117 + } 118 + 119 + template <typename Argtype> void count_argument(int& ints, int& fps) { ints++; } 120 + template <> void count_argument<float>(int& ints, int& fps) { fps++; } 121 + template <> void count_argument<double>(int& ints, int& fps) { fps++; } 122 + 123 + template <typename ...Args> 124 + class handle_arguments; 125 + 126 + template <> 127 + class handle_arguments<> 128 + { 129 + public: 130 + static void generate(Context& context, int index = 0) 131 + { 132 + } 133 + 134 + static void count(int& ints, int& fps) 135 + { 136 + } 137 + }; 138 + 139 + template <typename Arg0, typename ...Args> 140 + class handle_arguments<Arg0, Args...> 141 + { 142 + public: 143 + static void generate(Context& ctxt, int index = 0) 144 + { 145 + std::cout << "\t// argument #" << index << "\n"; 146 + copy_argument<Arg0>(ctxt); 147 + handle_arguments<Args...>::generate(ctxt, index+1); 148 + } 149 + 150 + static void count(int& ints, int& fps) 151 + { 152 + count_argument<Arg0>(ints, fps); 153 + handle_arguments<Args...>::count(ints, fps); 154 + } 155 + }; 156 + 157 + template <typename Retval, typename ...Args> 158 + class Stubifier; 159 + 160 + template <typename Retval, typename ...Args> 161 + class Stubifier<Retval(Args...)> : public Context 162 + { 163 + public: 164 + Stubifier(const char* name) 165 + : Context(name) 166 + { 167 + } 168 + 169 + void generate() 170 + { 171 + int stackalign = 4; // for return address of the call to this stub 172 + int ints = 0, fps = 0; 173 + 174 + _strings.push_back(AssemblyString{ std::string("_name_") + _name, _name }); 175 + 176 + std::cout << ".globl _" << _name << "\n_" 177 + << _name << ":\n" 178 + "\tprologue\n"; 179 + 180 + std::cout << "\t// Get real implementation\n"; 181 + std::cout << "\tmovq _" << _name << "_impl(%rip), %r10\n"; 182 + std::cout << "\ttestq %r10, %r10\n" 183 + "\tjnz 1f\n" 184 + "\tloadfunc _name_" << _name << ", _" << _name << "_impl\n"; 185 + 186 + std::cout << "1:\n"; 187 + handle_arguments<Args...>::count(ints, fps); 188 + 189 + if (ints >= 1) 190 + { 191 + stackalign += 4; // calee save edi 192 + if (ints >= 2) 193 + { 194 + stackalign += 4; // calee save esi 195 + if (ints > 6) 196 + stackalign += (ints-6) * 8; 197 + } 198 + } 199 + if (fps > 8) 200 + stackalign += (fps-8) * 16; 201 + 202 + // The stack must be 16-byte aligned 203 + stackalign = (stackalign + 15) / 16; 204 + stackalign *= 16; 205 + stackalign -= 4; // subtract the 4 bytes we had from the start 206 + 207 + // Arguments on the stack are now farther away 208 + _esp_offset += stackalign; 209 + 210 + std::cout << "\t// shift stack for alignment and/or extra stuff on stack\n"; 211 + std::cout << "\tsubq $" << stackalign << ", %rsp\n"; 212 + 213 + // esi and edi are calee save 214 + if (ints >= 1) 215 + { 216 + std::cout << "\t// calee save registers\n"; 217 + std::cout << "\tmovl %edi, " << stackalign-4 << "(%rsp)\n"; 218 + if (ints >= 2) 219 + std::cout << "\tmovl %esi, " << stackalign-8 << "(%rsp)\n"; 220 + } 221 + 222 + handle_arguments<Args...>::generate(*this); 223 + 224 + // call the implementation 225 + std::cout << "\t// call the implementation\n" 226 + "\tcallq *%r10\n"; 227 + 228 + handle_retval<Retval>(); 229 + 230 + // restore edi and esi 231 + if (ints >= 1) 232 + { 233 + std::cout << "\t// restore calee save registers\n"; 234 + if (ints >= 2) 235 + std::cout << "\tmovl " << stackalign-8 << "(%rsp), %esi\n"; 236 + std::cout << "\tmovl " << stackalign-4 << "(%rsp), %edi\n"; 237 + } 238 + 239 + std::cout << "\taddq $" << stackalign << ", %rsp\n"; 240 + 241 + std::cout << "\tepilogue\n" 242 + "// end of " << _name << "\n\n"; 243 + std::cout << ".zerofill __DATA,__bss,_" << _name << "_impl,8,3\n"; 244 + } 245 + 246 + }; 247 + 248 + void print_init() 249 + { 250 + std::cout << ".zerofill __DATA,__bss,_lib_handle,8,3\n"; 251 + 252 + std::cout << ".code64\n"; 253 + std::cout << "_initializer:\n" 254 + "\tpushq %rdi\n" 255 + "\tmovq L__darling_elfcalls$non_lazy_ptr(%rip), %rax\n" 256 + "\tmovq (%rax), %rax\n" 257 + "\tmovq _library_name(%rip), %rdi\n" 258 + "\tcallq *(%rax)\n" 259 + "\tmovq %rax, _lib_handle(%rip)\n" 260 + "\tpopq %rdi\n" 261 + "\tret\n\n"; 262 + 263 + std::cout << "_destructor:\n" 264 + "\tpushq %rdi\n" 265 + "\tmovq L__darling_elfcalls$non_lazy_ptr(%rip), %rcx\n" 266 + "\tmovq (%rcx), %rcx\n" 267 + "\tmovq _lib_handle(%rip), %rdi\n" 268 + "\tcallq *8(%rcx)\n" 269 + "\tpopq %rdi\n" 270 + "\tret\n\n"; 271 + 272 + std::cout << ".code32\n"; 273 + std::cout << ".section __DATA,__mod_init_func,mod_init_funcs\n" 274 + ".align 2\n" 275 + ".long _initializer\n" 276 + ".section __DATA,__mod_term_func,mod_term_funcs\n" 277 + ".align 2\n" 278 + ".long _destructor\n\n"; 279 + } 280 + 281 + #define STUBIFY(name) Stubifier<decltype(name)>(#name).generate() 282 + 283 + void produce_stubs(); 284 + extern const char* library_name; 285 + 286 + int main() 287 + { 288 + _strings.push_back(AssemblyString{ "_library_name", library_name }); 289 + 290 + std::cout << ".section __TEXT,__text,regular,pure_instructions\n\n"; 291 + 292 + std::cout << ".macro prologue\n" 293 + "\tsubl $$8, %esp\n" 294 + "\tmovl $$0x33, 4(%esp)\n" 295 + "\tleal 2f, %eax\n" 296 + "\tmovl %eax, (%esp)\n" 297 + "\tlret\n" 298 + /* Now in 64-bit mode */ 299 + "2:\n" \ 300 + ".code64\n" \ 301 + ".endmacro\n\n"; 302 + 303 + std::cout << ".macro epilogue\n" 304 + /* Transition 64->32 */ 305 + "\tsubq $$8, %rsp\n" 306 + "\tleaq 3f, %rcx\n" 307 + "\tmovl $$0x23, 4(%rsp)\n" 308 + "\tmovl %ecx, (%rsp)\n" 309 + "\tlret\n" 310 + "3:\n" 311 + ".code32\n" 312 + "\tpush $$0x2b\n" 313 + "\tpop %ds\n" 314 + "\tret\n" 315 + ".endmacro\n\n"; 316 + 317 + std::cout << ".macro loadfunc\n" 318 + "\tpushq %rdi\n" 319 + "\tpushq %rsi\n" 320 + "\tmovq _lib_handle(%rip), %rdi\n" 321 + "\tmovq $0(%rip), %rsi\n" 322 + "\tmovq L__darling_elfcalls$$non_lazy_ptr(%rip), %rax\n" 323 + "\tmovq (%rax), %rax\n" 324 + "\tcallq *16(%rax)\n" 325 + "\tmovq %rax, $1\n" 326 + "\tmovq %rax, %r10\n" 327 + "\tpopq %rsi\n" 328 + "\tpopq %rdi\n" 329 + ".endmacro\n\n"; 330 + 331 + print_init(); 332 + produce_stubs(); 333 + 334 + std::cout << ".section __TEXT,__cstring,cstring_literals\n"; 335 + for (const AssemblyString& str : _strings) 336 + { 337 + std::cout << "L_." << str.name.c_str() << ": .asciz \"" << str.value.c_str() << "\"\n"; 338 + std::cout << str.name.c_str() << ": .long L_." << str.name.c_str() << std::endl; 339 + } 340 + std::cout << std::endl; 341 + 342 + std::cout << ".section __IMPORT,__pointers,non_lazy_symbol_pointers\n" 343 + "L__darling_elfcalls$non_lazy_ptr:\n" 344 + ".indirect_symbol __darling_elfcalls\n" 345 + ".long 0\n\n"; 346 + 347 + std::cout << ".subsections_via_symbols\n\n"; 348 + 349 + return 0; 350 + } 351 + 352 + #include "produce_stubs.h" 353 + 354 +