[NFC] Fixed indentation issue (#116942)
[llvm-project.git] / libunwind / test / aix_signal_unwind.pass.sh.S
blob2c0cf140fe26720c8da447b52028472bbd6dc6d9
1 //===----------------------------------------------------------------------===//
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 //===----------------------------------------------------------------------===//
9 // Test that _Unwind_Backtrace() walks up from a signal handler and produces
10 // a correct traceback when the function raising the signal does not save
11 // the link register or does not store the stack back chain.
13 // REQUIRES: target={{.+}}-aix{{.*}}
15 // Test when the function raising the signal does not save the link register
16 // RUN: %{cxx} -x c++ %s -o %t.exe -DCXX_CODE %{flags} %{compile_flags}
17 // RUN: %{exec} %t.exe
19 // Test when the function raising the signal does not store stack back chain.
20 // RUN: %{cxx} -x c++ -c %s -o %t1.o -DCXX_CODE -DNOBACKCHAIN %{flags} \
21 // RUN:   %{compile_flags}
22 // RUN: %{cxx} -c %s -o %t2.o %{flags} %{compile_flags}
23 // RUN: %{cxx} -o %t1.exe %t1.o %t2.o %{flags} %{link_flags}
24 // RUN: %{exec} %t1.exe
26 #ifdef CXX_CODE
28 #undef NDEBUG
29 #include <assert.h>
30 #include <signal.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <sys/debug.h>
35 #include <unwind.h>
37 #define NAME_ARRAY_SIZE 10
38 #define NAMES_EXPECTED   6
40 const char* namesExpected[] = {"handler", "abc", "bar", "foo", "main",
41                                "__start"};
42 char *namesObtained[NAME_ARRAY_SIZE] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
44 int funcIndex = 0;
46 // Get the function name from traceback table.
47 char *getFuncName(uintptr_t pc, uint16_t *nameLen) {
48   uint32_t *p = reinterpret_cast<uint32_t *>(pc);
50   // Keep looking forward until a word of 0 is found. The traceback
51   // table starts at the following word.
52   while (*p)
53     ++p;
54   tbtable *TBTable = reinterpret_cast<tbtable *>(p + 1);
56   if (!TBTable->tb.name_present)
57     return NULL;
59   // Get to the optional portion of the traceback table.
60   p = reinterpret_cast<uint32_t *>(&TBTable->tb_ext);
62   // Skip field parminfo if it exists.
63   if (TBTable->tb.fixedparms || TBTable->tb.floatparms)
64     ++p;
66   // Skip field tb_offset if it exists.
67   if (TBTable->tb.has_tboff)
68     ++p;
70   // Skip field hand_mask if it exists.
71   if (TBTable->tb.int_hndl)
72     ++p;
74   // Skip fields ctl_info and ctl_info_disp if they exist.
75   if (TBTable->tb.has_ctl)
76     p += 1 + *p;
78   *nameLen = *reinterpret_cast<uint16_t *>(p);
79   return reinterpret_cast<char *>(p) + sizeof(uint16_t);
82 _Unwind_Reason_Code callBack(struct _Unwind_Context *uc, void *arg) {
83   (void)arg;
84   uint16_t nameLen;
85   uintptr_t ip = _Unwind_GetIP(uc);
86   if (funcIndex < NAME_ARRAY_SIZE)
87     namesObtained[funcIndex++] = strndup(getFuncName(ip, &nameLen), nameLen);
88   return _URC_NO_REASON;
91 extern "C" void handler(int signum) {
92   (void)signum;
93   // Walk stack frames for traceback.
94   _Unwind_Backtrace(callBack, NULL);
96   // Verify the traceback.
97   assert(funcIndex <= NAMES_EXPECTED && "Obtained names more than expected");
98   for (int i = 0; i < funcIndex; ++i) {
99     assert(!strcmp(namesExpected[i], namesObtained[i]) &&
100            "Function names do not match");
101     free(namesObtained[i]);
102   }
103   exit(0);
106 #ifdef NOBACKCHAIN
107 // abc() is in assembly. It raises signal SIGSEGV and does not store
108 // the stack back chain.
109 extern "C" void abc();
111 #else
112 volatile int *null = 0;
114 // abc() raises signal SIGSEGV and does not save the link register.
115 extern "C" __attribute__((noinline)) void abc() {
116   // Produce a SIGSEGV.
117   *null = 0;
119 #endif
121 extern "C" __attribute__((noinline)) void bar() {
122   abc();
125 extern "C" __attribute__((noinline)) void foo() {
126   bar();
129 int main() {
130   // Set signal handler for SIGSEGV.
131   signal(SIGSEGV, handler);
132   foo();
135 #else // Assembly code for abc().
136 // This assembly code is similar to the following C code but it saves the
137 // link register.
139 // int *badp = 0;
140 // void abc() {
141 //   *badp = 0;
142 // }
144 #ifdef __64BIT__
145         .csect [PR],5
146         .file   "abc.c"
147         .globl  abc[DS]                 # -- Begin function abc
148         .globl  .abc
149         .align  4
150         .csect abc[DS],3
151         .vbyte  8, .abc                 # @abc
152         .vbyte  8, TOC[TC0]
153         .vbyte  8, 0
154         .csect [PR],5
155 .abc:
156 # %bb.0:                                # %entry
157         mflr 0
158         std 0, 16(1)
159         ld 3, L..C0(2)                  # @badp
160         bl $+4
161         ld 4, 0(3)
162         li 3, 0
163         stw 3, 0(4)
164         ld 0, 16(1)
165         mtlr 0
166         blr
167 L..abc0:
168         .vbyte  4, 0x00000000           # Traceback table begin
169         .byte   0x00                    # Version = 0
170         .byte   0x09                    # Language = CPlusPlus
171         .byte   0x20                    # -IsGlobaLinkage, -IsOutOfLineEpilogOrPrologue
172                                         # +HasTraceBackTableOffset, -IsInternalProcedure
173                                         # -HasControlledStorage, -IsTOCless
174                                         # -IsFloatingPointPresent
175                                         # -IsFloatingPointOperationLogOrAbortEnabled
176         .byte   0x61                    # -IsInterruptHandler, +IsFunctionNamePresent, +IsAllocaUsed
177                                         # OnConditionDirective = 0, -IsCRSaved, +IsLRSaved
178         .byte   0x00                    # -IsBackChainStored, -IsFixup, NumOfFPRsSaved = 0
179         .byte   0x01                    # -HasExtensionTable, -HasVectorInfo, NumOfGPRsSaved = 1
180         .byte   0x00                    # NumberOfFixedParms = 0
181         .byte   0x01                    # NumberOfFPParms = 0, +HasParmsOnStack
182         .vbyte  4, L..abc0-.abc         # Function size
183         .vbyte  2, 0x0003               # Function name len = 3
184         .byte   "abc"                   # Function Name
185         .byte   0x1f                    # AllocaUsed
186                                         # -- End function
187         .csect badp[RW],3
188         .globl  badp[RW]                # @badp
189         .align  3
190         .vbyte  8, 0
191         .toc
192 L..C0:
193         .tc badp[TC],badp[RW]
194 #else
195         .csect [PR],5
196         .file   "abc.c"
197         .globl  abc[DS]                 # -- Begin function abc
198         .globl  .abc
199         .align  4
200         .csect abc[DS],2
201         .vbyte  4, .abc                 # @abc
202         .vbyte  4, TOC[TC0]
203         .vbyte  4, 0
204         .csect [PR],5
205 .abc:
206 # %bb.0:                                # %entry
207         mflr 0
208         stw 0, 8(1)
209         lwz 3, L..C0(2)                 # @badp
210         bl $+4
211         lwz 4, 0(3)
212         li 3, 0
213         stw 3, 0(4)
214         lwz 0, 8(1)
215         mtlr 0
216         blr
217 L..abc0:
218         .vbyte  4, 0x00000000           # Traceback table begin
219         .byte   0x00                    # Version = 0
220         .byte   0x09                    # Language = CPlusPlus
221         .byte   0x20                    # -IsGlobaLinkage, -IsOutOfLineEpilogOrPrologue
222                                         # +HasTraceBackTableOffset, -IsInternalProcedure
223                                         # -HasControlledStorage, -IsTOCless
224                                         # -IsFloatingPointPresent
225                                         # -IsFloatingPointOperationLogOrAbortEnabled
226         .byte   0x61                    # -IsInterruptHandler, +IsFunctionNamePresent, +IsAllocaUsed
227                                         # OnConditionDirective = 0, -IsCRSaved, +IsLRSaved
228         .byte   0x00                    # -IsBackChainStored, -IsFixup, NumOfFPRsSaved = 0
229         .byte   0x01                    # -HasExtensionTable, -HasVectorInfo, NumOfGPRsSaved = 1
230         .byte   0x00                    # NumberOfFixedParms = 0
231         .byte   0x01                    # NumberOfFPParms = 0, +HasParmsOnStack
232         .vbyte  4, L..abc0-.abc         # Function size
233         .vbyte  2, 0x0003               # Function name len = 3
234         .byte   "abc"                   # Function Name
235         .byte   0x1f                    # AllocaUsed
236                                         # -- End function
237         .csect badp[RW],2
238         .globl  badp[RW]                # @badp
239         .align  2
240         .vbyte  4, 0
241         .toc
242 L..C0:
243         .tc badp[TC],badp[RW]
244 #endif // __64BIT__
245 #endif // CXX_CODE