1 //===-- ABIMacOSX_i386.cpp ------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "ABIMacOSX_i386.h"
10 
11 #include <vector>
12 
13 #include "llvm/ADT/STLExtras.h"
14 #include "llvm/ADT/Triple.h"
15 
16 #include "lldb/Core/Module.h"
17 #include "lldb/Core/PluginManager.h"
18 #include "lldb/Core/ValueObjectConstResult.h"
19 #include "lldb/Symbol/UnwindPlan.h"
20 #include "lldb/Target/Process.h"
21 #include "lldb/Target/RegisterContext.h"
22 #include "lldb/Target/Target.h"
23 #include "lldb/Target/Thread.h"
24 #include "lldb/Utility/ConstString.h"
25 #include "lldb/Utility/RegisterValue.h"
26 #include "lldb/Utility/Scalar.h"
27 #include "lldb/Utility/Status.h"
28 
29 using namespace lldb;
30 using namespace lldb_private;
31 
32 LLDB_PLUGIN_DEFINE(ABIMacOSX_i386)
33 
34 enum {
35   dwarf_eax = 0,
36   dwarf_ecx,
37   dwarf_edx,
38   dwarf_ebx,
39   dwarf_esp,
40   dwarf_ebp,
41   dwarf_esi,
42   dwarf_edi,
43   dwarf_eip,
44 };
45 
46 size_t ABIMacOSX_i386::GetRedZoneSize() const { return 0; }
47 
48 // Static Functions
49 
50 ABISP
51 ABIMacOSX_i386::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) {
52   if ((arch.GetTriple().getArch() == llvm::Triple::x86) &&
53       (arch.GetTriple().isMacOSX() || arch.GetTriple().isiOS() ||
54        arch.GetTriple().isWatchOS())) {
55     return ABISP(
56         new ABIMacOSX_i386(std::move(process_sp), MakeMCRegisterInfo(arch)));
57   }
58   return ABISP();
59 }
60 
61 bool ABIMacOSX_i386::PrepareTrivialCall(Thread &thread, addr_t sp,
62                                         addr_t func_addr, addr_t return_addr,
63                                         llvm::ArrayRef<addr_t> args) const {
64   RegisterContext *reg_ctx = thread.GetRegisterContext().get();
65   if (!reg_ctx)
66     return false;
67   uint32_t pc_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(
68       eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
69   uint32_t sp_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(
70       eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
71 
72   // When writing a register value down to memory, the register info used to
73   // write memory just needs to have the correct size of a 32 bit register, the
74   // actual register it pertains to is not important, just the size needs to be
75   // correct. Here we use "eax"...
76   const RegisterInfo *reg_info_32 = reg_ctx->GetRegisterInfoByName("eax");
77   if (!reg_info_32)
78     return false; // TODO this should actually never happen
79 
80   // Make room for the argument(s) on the stack
81 
82   Status error;
83   RegisterValue reg_value;
84 
85   // Write any arguments onto the stack
86   sp -= 4 * args.size();
87 
88   // Align the SP
89   sp &= ~(16ull - 1ull); // 16-byte alignment
90 
91   addr_t arg_pos = sp;
92 
93   for (addr_t arg : args) {
94     reg_value.SetUInt32(arg);
95     error = reg_ctx->WriteRegisterValueToMemory(
96         reg_info_32, arg_pos, reg_info_32->byte_size, reg_value);
97     if (error.Fail())
98       return false;
99     arg_pos += 4;
100   }
101 
102   // The return address is pushed onto the stack (yes after we just set the
103   // alignment above!).
104   sp -= 4;
105   reg_value.SetUInt32(return_addr);
106   error = reg_ctx->WriteRegisterValueToMemory(
107       reg_info_32, sp, reg_info_32->byte_size, reg_value);
108   if (error.Fail())
109     return false;
110 
111   // %esp is set to the actual stack value.
112 
113   if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_num, sp))
114     return false;
115 
116   // %eip is set to the address of the called function.
117 
118   if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_num, func_addr))
119     return false;
120 
121   return true;
122 }
123 
124 static bool ReadIntegerArgument(Scalar &scalar, unsigned int bit_width,
125                                 bool is_signed, Process *process,
126                                 addr_t &current_stack_argument) {
127 
128   uint32_t byte_size = (bit_width + (8 - 1)) / 8;
129   Status error;
130   if (process->ReadScalarIntegerFromMemory(current_stack_argument, byte_size,
131                                            is_signed, scalar, error)) {
132     current_stack_argument += byte_size;
133     return true;
134   }
135   return false;
136 }
137 
138 bool ABIMacOSX_i386::GetArgumentValues(Thread &thread,
139                                        ValueList &values) const {
140   unsigned int num_values = values.GetSize();
141   unsigned int value_index;
142 
143   // Get the pointer to the first stack argument so we have a place to start
144   // when reading data
145 
146   RegisterContext *reg_ctx = thread.GetRegisterContext().get();
147 
148   if (!reg_ctx)
149     return false;
150 
151   addr_t sp = reg_ctx->GetSP(0);
152 
153   if (!sp)
154     return false;
155 
156   addr_t current_stack_argument = sp + 4; // jump over return address
157 
158   for (value_index = 0; value_index < num_values; ++value_index) {
159     Value *value = values.GetValueAtIndex(value_index);
160 
161     if (!value)
162       return false;
163 
164     // We currently only support extracting values with Clang QualTypes. Do we
165     // care about others?
166     CompilerType compiler_type(value->GetCompilerType());
167     llvm::Optional<uint64_t> bit_size = compiler_type.GetBitSize(&thread);
168     if (bit_size) {
169       bool is_signed;
170       if (compiler_type.IsIntegerOrEnumerationType(is_signed))
171         ReadIntegerArgument(value->GetScalar(), *bit_size, is_signed,
172                             thread.GetProcess().get(), current_stack_argument);
173       else if (compiler_type.IsPointerType())
174         ReadIntegerArgument(value->GetScalar(), *bit_size, false,
175                             thread.GetProcess().get(), current_stack_argument);
176     }
177   }
178 
179   return true;
180 }
181 
182 Status ABIMacOSX_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp,
183                                             lldb::ValueObjectSP &new_value_sp) {
184   Status error;
185   if (!new_value_sp) {
186     error.SetErrorString("Empty value object for return value.");
187     return error;
188   }
189 
190   CompilerType compiler_type = new_value_sp->GetCompilerType();
191   if (!compiler_type) {
192     error.SetErrorString("Null clang type for return value.");
193     return error;
194   }
195 
196   Thread *thread = frame_sp->GetThread().get();
197 
198   bool is_signed;
199   uint32_t count;
200   bool is_complex;
201 
202   RegisterContext *reg_ctx = thread->GetRegisterContext().get();
203 
204   bool set_it_simple = false;
205   if (compiler_type.IsIntegerOrEnumerationType(is_signed) ||
206       compiler_type.IsPointerType()) {
207     DataExtractor data;
208     Status data_error;
209     size_t num_bytes = new_value_sp->GetData(data, data_error);
210     if (data_error.Fail()) {
211       error.SetErrorStringWithFormat(
212           "Couldn't convert return value to raw data: %s",
213           data_error.AsCString());
214       return error;
215     }
216     lldb::offset_t offset = 0;
217     if (num_bytes <= 8) {
218       const RegisterInfo *eax_info = reg_ctx->GetRegisterInfoByName("eax", 0);
219       if (num_bytes <= 4) {
220         uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
221 
222         if (reg_ctx->WriteRegisterFromUnsigned(eax_info, raw_value))
223           set_it_simple = true;
224       } else {
225         uint32_t raw_value = data.GetMaxU32(&offset, 4);
226 
227         if (reg_ctx->WriteRegisterFromUnsigned(eax_info, raw_value)) {
228           const RegisterInfo *edx_info =
229               reg_ctx->GetRegisterInfoByName("edx", 0);
230           uint32_t raw_value = data.GetMaxU32(&offset, num_bytes - offset);
231 
232           if (reg_ctx->WriteRegisterFromUnsigned(edx_info, raw_value))
233             set_it_simple = true;
234         }
235       }
236     } else {
237       error.SetErrorString("We don't support returning longer than 64 bit "
238                            "integer values at present.");
239     }
240   } else if (compiler_type.IsFloatingPointType(count, is_complex)) {
241     if (is_complex)
242       error.SetErrorString(
243           "We don't support returning complex values at present");
244     else
245       error.SetErrorString(
246           "We don't support returning float values at present");
247   }
248 
249   if (!set_it_simple)
250     error.SetErrorString(
251         "We only support setting simple integer return types at present.");
252 
253   return error;
254 }
255 
256 ValueObjectSP
257 ABIMacOSX_i386::GetReturnValueObjectImpl(Thread &thread,
258                                          CompilerType &compiler_type) const {
259   Value value;
260   ValueObjectSP return_valobj_sp;
261 
262   if (!compiler_type)
263     return return_valobj_sp;
264 
265   // value.SetContext (Value::eContextTypeClangType,
266   // compiler_type.GetOpaqueQualType());
267   value.SetCompilerType(compiler_type);
268 
269   RegisterContext *reg_ctx = thread.GetRegisterContext().get();
270   if (!reg_ctx)
271     return return_valobj_sp;
272 
273   bool is_signed;
274 
275   if (compiler_type.IsIntegerOrEnumerationType(is_signed)) {
276     llvm::Optional<uint64_t> bit_width = compiler_type.GetBitSize(&thread);
277     if (!bit_width)
278       return return_valobj_sp;
279     unsigned eax_id =
280         reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB];
281     unsigned edx_id =
282         reg_ctx->GetRegisterInfoByName("edx", 0)->kinds[eRegisterKindLLDB];
283 
284     switch (*bit_width) {
285     default:
286     case 128:
287       // Scalar can't hold 128-bit literals, so we don't handle this
288       return return_valobj_sp;
289     case 64:
290       uint64_t raw_value;
291       raw_value =
292           thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
293           0xffffffff;
294       raw_value |=
295           (thread.GetRegisterContext()->ReadRegisterAsUnsigned(edx_id, 0) &
296            0xffffffff)
297           << 32;
298       if (is_signed)
299         value.GetScalar() = (int64_t)raw_value;
300       else
301         value.GetScalar() = (uint64_t)raw_value;
302       break;
303     case 32:
304       if (is_signed)
305         value.GetScalar() = (int32_t)(
306             thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
307             0xffffffff);
308       else
309         value.GetScalar() = (uint32_t)(
310             thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
311             0xffffffff);
312       break;
313     case 16:
314       if (is_signed)
315         value.GetScalar() = (int16_t)(
316             thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
317             0xffff);
318       else
319         value.GetScalar() = (uint16_t)(
320             thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
321             0xffff);
322       break;
323     case 8:
324       if (is_signed)
325         value.GetScalar() = (int8_t)(
326             thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
327             0xff);
328       else
329         value.GetScalar() = (uint8_t)(
330             thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
331             0xff);
332       break;
333     }
334   } else if (compiler_type.IsPointerType()) {
335     unsigned eax_id =
336         reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB];
337     uint32_t ptr =
338         thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
339         0xffffffff;
340     value.GetScalar() = ptr;
341   } else {
342     // not handled yet
343     return return_valobj_sp;
344   }
345 
346   // If we get here, we have a valid Value, so make our ValueObject out of it:
347 
348   return_valobj_sp = ValueObjectConstResult::Create(
349       thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
350   return return_valobj_sp;
351 }
352 
353 // This defines the CFA as esp+4
354 // the saved pc is at CFA-4 (i.e. esp+0)
355 // The saved esp is CFA+0
356 
357 bool ABIMacOSX_i386::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) {
358   unwind_plan.Clear();
359   unwind_plan.SetRegisterKind(eRegisterKindDWARF);
360 
361   uint32_t sp_reg_num = dwarf_esp;
362   uint32_t pc_reg_num = dwarf_eip;
363 
364   UnwindPlan::RowSP row(new UnwindPlan::Row);
365   row->GetCFAValue().SetIsRegisterPlusOffset(sp_reg_num, 4);
366   row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, -4, false);
367   row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);
368   unwind_plan.AppendRow(row);
369   unwind_plan.SetSourceName("i386 at-func-entry default");
370   unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
371   return true;
372 }
373 
374 // This defines the CFA as ebp+8
375 // The saved pc is at CFA-4 (i.e. ebp+4)
376 // The saved ebp is at CFA-8 (i.e. ebp+0)
377 // The saved esp is CFA+0
378 
379 bool ABIMacOSX_i386::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {
380   unwind_plan.Clear();
381   unwind_plan.SetRegisterKind(eRegisterKindDWARF);
382 
383   uint32_t fp_reg_num = dwarf_ebp;
384   uint32_t sp_reg_num = dwarf_esp;
385   uint32_t pc_reg_num = dwarf_eip;
386 
387   UnwindPlan::RowSP row(new UnwindPlan::Row);
388   const int32_t ptr_size = 4;
389 
390   row->GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num, 2 * ptr_size);
391   row->SetOffset(0);
392   row->SetUnspecifiedRegistersAreUndefined(true);
393 
394   row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
395   row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true);
396   row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);
397 
398   unwind_plan.AppendRow(row);
399   unwind_plan.SetSourceName("i386 default unwind plan");
400   unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
401   unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
402   unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo);
403   return true;
404 }
405 
406 bool ABIMacOSX_i386::RegisterIsVolatile(const RegisterInfo *reg_info) {
407   return !RegisterIsCalleeSaved(reg_info);
408 }
409 
410 // v.
411 // http://developer.apple.com/library/mac/#documentation/developertools/Conceptual/LowLevelABI/130
412 // -IA-
413 // 32_Function_Calling_Conventions/IA32.html#//apple_ref/doc/uid/TP40002492-SW4
414 //
415 // This document ("OS X ABI Function Call Guide", chapter "IA-32 Function
416 // Calling Conventions") says that the following registers on i386 are
417 // preserved aka non-volatile aka callee-saved:
418 //
419 // ebx, ebp, esi, edi, esp
420 
421 bool ABIMacOSX_i386::RegisterIsCalleeSaved(const RegisterInfo *reg_info) {
422   if (reg_info) {
423     // Saved registers are ebx, ebp, esi, edi, esp, eip
424     const char *name = reg_info->name;
425     if (name[0] == 'e') {
426       switch (name[1]) {
427       case 'b':
428         if (name[2] == 'x' || name[2] == 'p')
429           return name[3] == '\0';
430         break;
431       case 'd':
432         if (name[2] == 'i')
433           return name[3] == '\0';
434         break;
435       case 'i':
436         if (name[2] == 'p')
437           return name[3] == '\0';
438         break;
439       case 's':
440         if (name[2] == 'i' || name[2] == 'p')
441           return name[3] == '\0';
442         break;
443       }
444     }
445     if (name[0] == 's' && name[1] == 'p' && name[2] == '\0') // sp
446       return true;
447     if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0') // fp
448       return true;
449     if (name[0] == 'p' && name[1] == 'c' && name[2] == '\0') // pc
450       return true;
451   }
452   return false;
453 }
454 
455 void ABIMacOSX_i386::Initialize() {
456   PluginManager::RegisterPlugin(
457       GetPluginNameStatic(), "Mac OS X ABI for i386 targets", CreateInstance);
458 }
459 
460 void ABIMacOSX_i386::Terminate() {
461   PluginManager::UnregisterPlugin(CreateInstance);
462 }
463