ThreadElfCore.cpp revision 327952
1254721Semaste//===-- ThreadElfCore.cpp --------------------------------------*- C++ -*-===//
2254721Semaste//
3254721Semaste//                     The LLVM Compiler Infrastructure
4254721Semaste//
5254721Semaste// This file is distributed under the University of Illinois Open Source
6254721Semaste// License. See LICENSE.TXT for details.
7254721Semaste//
8254721Semaste//===----------------------------------------------------------------------===//
9254721Semaste
10254721Semaste#include "lldb/Target/RegisterContext.h"
11254721Semaste#include "lldb/Target/StopInfo.h"
12254721Semaste#include "lldb/Target/Target.h"
13254721Semaste#include "lldb/Target/Unwind.h"
14321369Sdim#include "lldb/Utility/DataExtractor.h"
15321369Sdim#include "lldb/Utility/Log.h"
16254721Semaste
17280031Sdim#include "Plugins/Process/Utility/RegisterContextFreeBSD_i386.h"
18280031Sdim#include "Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h"
19280031Sdim#include "Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h"
20280031Sdim#include "Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h"
21327952Sdim#include "Plugins/Process/Utility/RegisterContextLinux_i386.h"
22327952Sdim#include "Plugins/Process/Utility/RegisterContextLinux_mips.h"
23321369Sdim#include "Plugins/Process/Utility/RegisterContextLinux_mips64.h"
24327952Sdim#ifdef LLDB_ENABLE_ALL
25327952Sdim#include "Plugins/Process/Utility/RegisterContextLinux_s390x.h"
26327952Sdim#endif // LLDB_ENABLE_ALL
27314564Sdim#include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h"
28321369Sdim#include "Plugins/Process/Utility/RegisterContextNetBSD_x86_64.h"
29321369Sdim#include "Plugins/Process/Utility/RegisterContextOpenBSD_i386.h"
30321369Sdim#include "Plugins/Process/Utility/RegisterContextOpenBSD_x86_64.h"
31321369Sdim#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm.h"
32314564Sdim#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h"
33327952Sdim#include "Plugins/Process/Utility/RegisterInfoPOSIX_ppc64le.h"
34314564Sdim#include "ProcessElfCore.h"
35288943Sdim#include "RegisterContextPOSIXCore_arm.h"
36288943Sdim#include "RegisterContextPOSIXCore_arm64.h"
37258054Semaste#include "RegisterContextPOSIXCore_mips64.h"
38280031Sdim#include "RegisterContextPOSIXCore_powerpc.h"
39327952Sdim#include "RegisterContextPOSIXCore_ppc64le.h"
40327952Sdim#ifdef LLDB_ENABLE_ALL
41327952Sdim#include "RegisterContextPOSIXCore_s390x.h"
42327952Sdim#endif // LLDB_ENABLE_ALL
43258054Semaste#include "RegisterContextPOSIXCore_x86_64.h"
44314564Sdim#include "ThreadElfCore.h"
45254721Semaste
46254721Semasteusing namespace lldb;
47254721Semasteusing namespace lldb_private;
48254721Semaste
49254721Semaste//----------------------------------------------------------------------
50254721Semaste// Construct a Thread object with given data
51254721Semaste//----------------------------------------------------------------------
52314564SdimThreadElfCore::ThreadElfCore(Process &process, const ThreadData &td)
53314564Sdim    : Thread(process, td.tid), m_thread_name(td.name), m_thread_reg_ctx_sp(),
54327952Sdim      m_signo(td.signo), m_gpregset_data(td.gpregset), m_notes(td.notes) {}
55254721Semaste
56314564SdimThreadElfCore::~ThreadElfCore() { DestroyThread(); }
57254721Semaste
58314564Sdimvoid ThreadElfCore::RefreshStateAfterStop() {
59314564Sdim  GetRegisterContext()->InvalidateIfNeeded(false);
60254721Semaste}
61254721Semaste
62314564Sdimvoid ThreadElfCore::ClearStackFrames() {
63314564Sdim  Unwind *unwinder = GetUnwinder();
64314564Sdim  if (unwinder)
65314564Sdim    unwinder->Clear();
66314564Sdim  Thread::ClearStackFrames();
67254721Semaste}
68254721Semaste
69314564SdimRegisterContextSP ThreadElfCore::GetRegisterContext() {
70314564Sdim  if (m_reg_context_sp.get() == NULL) {
71314564Sdim    m_reg_context_sp = CreateRegisterContextForFrame(NULL);
72314564Sdim  }
73314564Sdim  return m_reg_context_sp;
74254721Semaste}
75254721Semaste
76254721SemasteRegisterContextSP
77314564SdimThreadElfCore::CreateRegisterContextForFrame(StackFrame *frame) {
78314564Sdim  RegisterContextSP reg_ctx_sp;
79314564Sdim  uint32_t concrete_frame_idx = 0;
80314564Sdim  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
81254721Semaste
82314564Sdim  if (frame)
83314564Sdim    concrete_frame_idx = frame->GetConcreteFrameIndex();
84254721Semaste
85314564Sdim  if (concrete_frame_idx == 0) {
86314564Sdim    if (m_thread_reg_ctx_sp)
87314564Sdim      return m_thread_reg_ctx_sp;
88254721Semaste
89314564Sdim    ProcessElfCore *process = static_cast<ProcessElfCore *>(GetProcess().get());
90314564Sdim    ArchSpec arch = process->GetArchitecture();
91314564Sdim    RegisterInfoInterface *reg_interface = NULL;
92262528Semaste
93314564Sdim    switch (arch.GetTriple().getOS()) {
94314564Sdim    case llvm::Triple::FreeBSD: {
95314564Sdim      switch (arch.GetMachine()) {
96314564Sdim      case llvm::Triple::aarch64:
97314564Sdim        reg_interface = new RegisterInfoPOSIX_arm64(arch);
98314564Sdim        break;
99314564Sdim      case llvm::Triple::arm:
100321369Sdim        reg_interface = new RegisterInfoPOSIX_arm(arch);
101314564Sdim        break;
102314564Sdim      case llvm::Triple::ppc:
103314564Sdim        reg_interface = new RegisterContextFreeBSD_powerpc32(arch);
104314564Sdim        break;
105314564Sdim      case llvm::Triple::ppc64:
106314564Sdim        reg_interface = new RegisterContextFreeBSD_powerpc64(arch);
107314564Sdim        break;
108314564Sdim      case llvm::Triple::mips64:
109314564Sdim        reg_interface = new RegisterContextFreeBSD_mips64(arch);
110314564Sdim        break;
111314564Sdim      case llvm::Triple::x86:
112314564Sdim        reg_interface = new RegisterContextFreeBSD_i386(arch);
113314564Sdim        break;
114314564Sdim      case llvm::Triple::x86_64:
115314564Sdim        reg_interface = new RegisterContextFreeBSD_x86_64(arch);
116314564Sdim        break;
117314564Sdim      default:
118314564Sdim        break;
119314564Sdim      }
120314564Sdim      break;
121314564Sdim    }
122276479Sdim
123321369Sdim    case llvm::Triple::NetBSD: {
124321369Sdim      switch (arch.GetMachine()) {
125321369Sdim      case llvm::Triple::x86_64:
126321369Sdim        reg_interface = new RegisterContextNetBSD_x86_64(arch);
127321369Sdim        break;
128321369Sdim      default:
129321369Sdim        break;
130321369Sdim      }
131321369Sdim      break;
132321369Sdim    }
133321369Sdim
134314564Sdim    case llvm::Triple::Linux: {
135314564Sdim      switch (arch.GetMachine()) {
136314564Sdim      case llvm::Triple::arm:
137321369Sdim        reg_interface = new RegisterInfoPOSIX_arm(arch);
138314564Sdim        break;
139314564Sdim      case llvm::Triple::aarch64:
140314564Sdim        reg_interface = new RegisterInfoPOSIX_arm64(arch);
141314564Sdim        break;
142321369Sdim      case llvm::Triple::mipsel:
143321369Sdim      case llvm::Triple::mips:
144321369Sdim        reg_interface = new RegisterContextLinux_mips(arch);
145321369Sdim        break;
146321369Sdim      case llvm::Triple::mips64el:
147321369Sdim      case llvm::Triple::mips64:
148321369Sdim        reg_interface = new RegisterContextLinux_mips64(arch);
149321369Sdim        break;
150327952Sdim      case llvm::Triple::ppc64le:
151327952Sdim        reg_interface = new RegisterInfoPOSIX_ppc64le(arch);
152327952Sdim        break;
153327952Sdim#ifdef LLDB_ENABLE_ALL
154327952Sdim      case llvm::Triple::systemz:
155327952Sdim        reg_interface = new RegisterContextLinux_s390x(arch);
156327952Sdim        break;
157327952Sdim#endif // LLDB_ENABLE_ALL
158314564Sdim      case llvm::Triple::x86:
159314564Sdim        reg_interface = new RegisterContextLinux_i386(arch);
160314564Sdim        break;
161314564Sdim      case llvm::Triple::x86_64:
162314564Sdim        reg_interface = new RegisterContextLinux_x86_64(arch);
163314564Sdim        break;
164314564Sdim      default:
165314564Sdim        break;
166314564Sdim      }
167314564Sdim      break;
168314564Sdim    }
169262528Semaste
170321369Sdim    case llvm::Triple::OpenBSD: {
171321369Sdim      switch (arch.GetMachine()) {
172321369Sdim      case llvm::Triple::aarch64:
173321369Sdim        reg_interface = new RegisterInfoPOSIX_arm64(arch);
174321369Sdim        break;
175321369Sdim      case llvm::Triple::arm:
176321369Sdim        reg_interface = new RegisterInfoPOSIX_arm(arch);
177321369Sdim        break;
178321369Sdim      case llvm::Triple::x86:
179321369Sdim        reg_interface = new RegisterContextOpenBSD_i386(arch);
180321369Sdim        break;
181321369Sdim      case llvm::Triple::x86_64:
182321369Sdim        reg_interface = new RegisterContextOpenBSD_x86_64(arch);
183321369Sdim        break;
184321369Sdim      default:
185321369Sdim        break;
186321369Sdim      }
187321369Sdim      break;
188321369Sdim    }
189321369Sdim
190314564Sdim    default:
191314564Sdim      break;
192314564Sdim    }
193262528Semaste
194314564Sdim    if (!reg_interface) {
195314564Sdim      if (log)
196314564Sdim        log->Printf("elf-core::%s:: Architecture(%d) or OS(%d) not supported",
197314564Sdim                    __FUNCTION__, arch.GetMachine(), arch.GetTriple().getOS());
198314564Sdim      assert(false && "Architecture or OS not supported");
199314564Sdim    }
200262528Semaste
201314564Sdim    switch (arch.GetMachine()) {
202314564Sdim    case llvm::Triple::aarch64:
203314564Sdim      m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_arm64(
204327952Sdim          *this, reg_interface, m_gpregset_data, m_notes));
205314564Sdim      break;
206314564Sdim    case llvm::Triple::arm:
207314564Sdim      m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_arm(
208327952Sdim          *this, reg_interface, m_gpregset_data, m_notes));
209314564Sdim      break;
210321369Sdim    case llvm::Triple::mipsel:
211321369Sdim    case llvm::Triple::mips:
212321369Sdim      m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_mips64(
213327952Sdim          *this, reg_interface, m_gpregset_data, m_notes));
214321369Sdim      break;
215314564Sdim    case llvm::Triple::mips64:
216321369Sdim    case llvm::Triple::mips64el:
217314564Sdim      m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_mips64(
218327952Sdim          *this, reg_interface, m_gpregset_data, m_notes));
219314564Sdim      break;
220314564Sdim    case llvm::Triple::ppc:
221314564Sdim    case llvm::Triple::ppc64:
222314564Sdim      m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_powerpc(
223327952Sdim          *this, reg_interface, m_gpregset_data, m_notes));
224314564Sdim      break;
225327952Sdim    case llvm::Triple::ppc64le:
226327952Sdim      m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_ppc64le(
227327952Sdim          *this, reg_interface, m_gpregset_data, m_notes));
228327952Sdim      break;
229327952Sdim#ifdef LLDB_ENABLE_ALL
230327952Sdim    case llvm::Triple::systemz:
231327952Sdim      m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_s390x(
232327952Sdim          *this, reg_interface, m_gpregset_data, m_notes));
233327952Sdim      break;
234327952Sdim#endif // LLDB_ENABLE_ALL
235314564Sdim    case llvm::Triple::x86:
236314564Sdim    case llvm::Triple::x86_64:
237314564Sdim      m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_x86_64(
238327952Sdim          *this, reg_interface, m_gpregset_data, m_notes));
239314564Sdim      break;
240314564Sdim    default:
241314564Sdim      break;
242314564Sdim    }
243262528Semaste
244314564Sdim    reg_ctx_sp = m_thread_reg_ctx_sp;
245314564Sdim  } else if (m_unwinder_ap.get()) {
246314564Sdim    reg_ctx_sp = m_unwinder_ap->CreateRegisterContextForFrame(frame);
247314564Sdim  }
248314564Sdim  return reg_ctx_sp;
249254721Semaste}
250254721Semaste
251314564Sdimbool ThreadElfCore::CalculateStopInfo() {
252314564Sdim  ProcessSP process_sp(GetProcess());
253314564Sdim  if (process_sp) {
254314564Sdim    SetStopInfo(StopInfo::CreateStopReasonWithSignal(*this, m_signo));
255314564Sdim    return true;
256314564Sdim  }
257314564Sdim  return false;
258254721Semaste}
259254721Semaste
260254721Semaste//----------------------------------------------------------------
261254721Semaste// Parse PRSTATUS from NOTE entry
262254721Semaste//----------------------------------------------------------------
263314564SdimELFLinuxPrStatus::ELFLinuxPrStatus() {
264314564Sdim  memset(this, 0, sizeof(ELFLinuxPrStatus));
265254721Semaste}
266254721Semaste
267327952Sdimsize_t ELFLinuxPrStatus::GetSize(const lldb_private::ArchSpec &arch) {
268321369Sdim  constexpr size_t mips_linux_pr_status_size_o32 = 96;
269321369Sdim  constexpr size_t mips_linux_pr_status_size_n32 = 72;
270321369Sdim  if (arch.IsMIPS()) {
271321369Sdim    std::string abi = arch.GetTargetABI();
272321369Sdim    assert(!abi.empty() && "ABI is not set");
273321369Sdim    if (!abi.compare("n64"))
274321369Sdim      return sizeof(ELFLinuxPrStatus);
275321369Sdim    else if (!abi.compare("o32"))
276321369Sdim      return mips_linux_pr_status_size_o32;
277321369Sdim    // N32 ABI
278321369Sdim    return mips_linux_pr_status_size_n32;
279321369Sdim  }
280321369Sdim  switch (arch.GetCore()) {
281321369Sdim  case lldb_private::ArchSpec::eCore_s390x_generic:
282321369Sdim  case lldb_private::ArchSpec::eCore_x86_64_x86_64:
283327952Sdim  case lldb_private::ArchSpec::eCore_ppc64le_generic:
284321369Sdim    return sizeof(ELFLinuxPrStatus);
285321369Sdim  case lldb_private::ArchSpec::eCore_x86_32_i386:
286321369Sdim  case lldb_private::ArchSpec::eCore_x86_32_i486:
287321369Sdim    return 72;
288321369Sdim  default:
289321369Sdim    return 0;
290321369Sdim  }
291321369Sdim}
292321369Sdim
293327952SdimStatus ELFLinuxPrStatus::Parse(const DataExtractor &data,
294327952Sdim                               const ArchSpec &arch) {
295321369Sdim  Status error;
296314564Sdim  if (GetSize(arch) > data.GetByteSize()) {
297314564Sdim    error.SetErrorStringWithFormat(
298314564Sdim        "NT_PRSTATUS size should be %zu, but the remaining bytes are: %" PRIu64,
299314564Sdim        GetSize(arch), data.GetByteSize());
300314564Sdim    return error;
301314564Sdim  }
302314564Sdim
303314564Sdim  // Read field by field to correctly account for endianess
304314564Sdim  // of both the core dump and the platform running lldb.
305314564Sdim  offset_t offset = 0;
306314564Sdim  si_signo = data.GetU32(&offset);
307314564Sdim  si_code = data.GetU32(&offset);
308314564Sdim  si_errno = data.GetU32(&offset);
309314564Sdim
310314564Sdim  pr_cursig = data.GetU16(&offset);
311314564Sdim  offset += 2; // pad
312314564Sdim
313314564Sdim  pr_sigpend = data.GetPointer(&offset);
314314564Sdim  pr_sighold = data.GetPointer(&offset);
315314564Sdim
316314564Sdim  pr_pid = data.GetU32(&offset);
317314564Sdim  pr_ppid = data.GetU32(&offset);
318314564Sdim  pr_pgrp = data.GetU32(&offset);
319314564Sdim  pr_sid = data.GetU32(&offset);
320314564Sdim
321314564Sdim  pr_utime.tv_sec = data.GetPointer(&offset);
322314564Sdim  pr_utime.tv_usec = data.GetPointer(&offset);
323314564Sdim
324314564Sdim  pr_stime.tv_sec = data.GetPointer(&offset);
325314564Sdim  pr_stime.tv_usec = data.GetPointer(&offset);
326314564Sdim
327314564Sdim  pr_cutime.tv_sec = data.GetPointer(&offset);
328314564Sdim  pr_cutime.tv_usec = data.GetPointer(&offset);
329314564Sdim
330314564Sdim  pr_cstime.tv_sec = data.GetPointer(&offset);
331314564Sdim  pr_cstime.tv_usec = data.GetPointer(&offset);
332314564Sdim
333314564Sdim  return error;
334254721Semaste}
335254721Semaste
336254721Semaste//----------------------------------------------------------------
337254721Semaste// Parse PRPSINFO from NOTE entry
338254721Semaste//----------------------------------------------------------------
339314564SdimELFLinuxPrPsInfo::ELFLinuxPrPsInfo() {
340314564Sdim  memset(this, 0, sizeof(ELFLinuxPrPsInfo));
341254721Semaste}
342254721Semaste
343327952Sdimsize_t ELFLinuxPrPsInfo::GetSize(const lldb_private::ArchSpec &arch) {
344321369Sdim  constexpr size_t mips_linux_pr_psinfo_size_o32_n32 = 128;
345321369Sdim  if (arch.IsMIPS()) {
346321369Sdim    uint8_t address_byte_size = arch.GetAddressByteSize();
347321369Sdim    if (address_byte_size == 8)
348321369Sdim      return sizeof(ELFLinuxPrPsInfo);
349321369Sdim    return mips_linux_pr_psinfo_size_o32_n32;
350321369Sdim  }
351321369Sdim
352321369Sdim  switch (arch.GetCore()) {
353321369Sdim  case lldb_private::ArchSpec::eCore_s390x_generic:
354321369Sdim  case lldb_private::ArchSpec::eCore_x86_64_x86_64:
355321369Sdim    return sizeof(ELFLinuxPrPsInfo);
356321369Sdim  case lldb_private::ArchSpec::eCore_x86_32_i386:
357321369Sdim  case lldb_private::ArchSpec::eCore_x86_32_i486:
358321369Sdim    return 124;
359321369Sdim  default:
360321369Sdim    return 0;
361321369Sdim  }
362321369Sdim}
363321369Sdim
364327952SdimStatus ELFLinuxPrPsInfo::Parse(const DataExtractor &data,
365327952Sdim                               const ArchSpec &arch) {
366321369Sdim  Status error;
367314564Sdim  ByteOrder byteorder = data.GetByteOrder();
368314564Sdim  if (GetSize(arch) > data.GetByteSize()) {
369314564Sdim    error.SetErrorStringWithFormat(
370314564Sdim        "NT_PRPSINFO size should be %zu, but the remaining bytes are: %" PRIu64,
371314564Sdim        GetSize(arch), data.GetByteSize());
372314564Sdim    return error;
373314564Sdim  }
374314564Sdim  size_t size = 0;
375314564Sdim  offset_t offset = 0;
376314564Sdim
377314564Sdim  pr_state = data.GetU8(&offset);
378314564Sdim  pr_sname = data.GetU8(&offset);
379314564Sdim  pr_zomb = data.GetU8(&offset);
380314564Sdim  pr_nice = data.GetU8(&offset);
381314564Sdim  if (data.GetAddressByteSize() == 8) {
382314564Sdim    // Word align the next field on 64 bit.
383314564Sdim    offset += 4;
384314564Sdim  }
385314564Sdim
386314564Sdim  pr_flag = data.GetPointer(&offset);
387314564Sdim
388321369Sdim  if (arch.IsMIPS()) {
389321369Sdim    // The pr_uid and pr_gid is always 32 bit irrespective of platforms
390321369Sdim    pr_uid = data.GetU32(&offset);
391321369Sdim    pr_gid = data.GetU32(&offset);
392321369Sdim  } else {
393314564Sdim  // 16 bit on 32 bit platforms, 32 bit on 64 bit platforms
394314564Sdim  pr_uid = data.GetMaxU64(&offset, data.GetAddressByteSize() >> 1);
395314564Sdim  pr_gid = data.GetMaxU64(&offset, data.GetAddressByteSize() >> 1);
396321369Sdim  }
397314564Sdim
398314564Sdim  pr_pid = data.GetU32(&offset);
399314564Sdim  pr_ppid = data.GetU32(&offset);
400314564Sdim  pr_pgrp = data.GetU32(&offset);
401314564Sdim  pr_sid = data.GetU32(&offset);
402314564Sdim
403314564Sdim  size = 16;
404314564Sdim  data.ExtractBytes(offset, size, byteorder, pr_fname);
405314564Sdim  offset += size;
406314564Sdim
407314564Sdim  size = 80;
408314564Sdim  data.ExtractBytes(offset, size, byteorder, pr_psargs);
409314564Sdim  offset += size;
410314564Sdim
411314564Sdim  return error;
412254721Semaste}
413254721Semaste
414314564Sdim//----------------------------------------------------------------
415314564Sdim// Parse SIGINFO from NOTE entry
416314564Sdim//----------------------------------------------------------------
417321369SdimELFLinuxSigInfo::ELFLinuxSigInfo() { memset(this, 0, sizeof(ELFLinuxSigInfo)); }
418321369Sdim
419321369Sdimsize_t ELFLinuxSigInfo::GetSize(const lldb_private::ArchSpec &arch) {
420321369Sdim  if (arch.IsMIPS())
421321369Sdim    return sizeof(ELFLinuxSigInfo);
422321369Sdim  switch (arch.GetCore()) {
423321369Sdim  case lldb_private::ArchSpec::eCore_x86_64_x86_64:
424321369Sdim    return sizeof(ELFLinuxSigInfo);
425321369Sdim  case lldb_private::ArchSpec::eCore_s390x_generic:
426321369Sdim  case lldb_private::ArchSpec::eCore_x86_32_i386:
427321369Sdim  case lldb_private::ArchSpec::eCore_x86_32_i486:
428321369Sdim    return 12;
429321369Sdim  default:
430321369Sdim    return 0;
431321369Sdim  }
432314564Sdim}
433314564Sdim
434327952SdimStatus ELFLinuxSigInfo::Parse(const DataExtractor &data, const ArchSpec &arch) {
435321369Sdim  Status error;
436314564Sdim  if (GetSize(arch) > data.GetByteSize()) {
437314564Sdim    error.SetErrorStringWithFormat(
438314564Sdim        "NT_SIGINFO size should be %zu, but the remaining bytes are: %" PRIu64,
439314564Sdim        GetSize(arch), data.GetByteSize());
440314564Sdim    return error;
441314564Sdim  }
442314564Sdim
443314564Sdim  // Parsing from a 32 bit ELF core file, and populating/reusing the structure
444314564Sdim  // properly, because the struct is for the 64 bit version
445314564Sdim  offset_t offset = 0;
446314564Sdim  si_signo = data.GetU32(&offset);
447314564Sdim  si_code = data.GetU32(&offset);
448314564Sdim  si_errno = data.GetU32(&offset);
449314564Sdim
450314564Sdim  return error;
451314564Sdim}
452