xref: /llvm-project/libunwind/test/libunwind_01.pass.cpp (revision db8c7e004a8acf74f40e0f7bc60066f26d43ccd9)
1282b3eb7SLouis Dionne // -*- C++ -*-
2282b3eb7SLouis Dionne //===----------------------------------------------------------------------===//
3282b3eb7SLouis Dionne //
4282b3eb7SLouis Dionne // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5282b3eb7SLouis Dionne // See https://llvm.org/LICENSE.txt for license information.
6282b3eb7SLouis Dionne // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7282b3eb7SLouis Dionne //
8282b3eb7SLouis Dionne //===----------------------------------------------------------------------===//
9282b3eb7SLouis Dionne 
1092bbcfaaSLouis Dionne // TODO: Investigate this failure on x86_64 macOS back deployment
11*db8c7e00SLouis Dionne // XFAIL: stdlib=system && target=x86_64-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11.0|12.0}}
1260fe1f59SLouis Dionne 
13cb055e51SLouis Dionne // TODO: Figure out why this fails with Memory Sanitizer.
14cb055e51SLouis Dionne // XFAIL: msan
15cb055e51SLouis Dionne 
167fab97f3SLogan Chien #include <libunwind.h>
177fab97f3SLogan Chien #include <stdlib.h>
188df257a6SAlex Richardson #include <stdio.h>
192f1ee56fSVitaly Buka #include <string.h>
207fab97f3SLogan Chien 
backtrace(int lower_bound)217fab97f3SLogan Chien void backtrace(int lower_bound) {
227fab97f3SLogan Chien   unw_context_t context;
237fab97f3SLogan Chien   unw_getcontext(&context);
247fab97f3SLogan Chien 
257fab97f3SLogan Chien   unw_cursor_t cursor;
267fab97f3SLogan Chien   unw_init_local(&cursor, &context);
277fab97f3SLogan Chien 
288df257a6SAlex Richardson   char buffer[1024];
298df257a6SAlex Richardson   unw_word_t offset = 0;
308df257a6SAlex Richardson 
317fab97f3SLogan Chien   int n = 0;
327fab97f3SLogan Chien   do {
338df257a6SAlex Richardson     n++;
348df257a6SAlex Richardson     if (unw_get_proc_name(&cursor, buffer, sizeof(buffer), &offset) == 0) {
358df257a6SAlex Richardson       fprintf(stderr, "Frame %d: %s+%p\n", n, buffer, (void*)offset);
368df257a6SAlex Richardson     } else {
378df257a6SAlex Richardson       fprintf(stderr, "Frame %d: Could not get name for cursor\n", n);
388df257a6SAlex Richardson     }
397fab97f3SLogan Chien     if (n > 100) {
407fab97f3SLogan Chien       abort();
417fab97f3SLogan Chien     }
427fab97f3SLogan Chien   } while (unw_step(&cursor) > 0);
437fab97f3SLogan Chien 
447fab97f3SLogan Chien   if (n < lower_bound) {
457fab97f3SLogan Chien     abort();
467fab97f3SLogan Chien   }
477fab97f3SLogan Chien }
487fab97f3SLogan Chien 
test1(int i)498df257a6SAlex Richardson __attribute__((noinline)) void test1(int i) {
508df257a6SAlex Richardson   fprintf(stderr, "starting %s\n", __func__);
517fab97f3SLogan Chien   backtrace(i);
528df257a6SAlex Richardson   fprintf(stderr, "finished %s\n", __func__); // ensure return address is saved
537fab97f3SLogan Chien }
547fab97f3SLogan Chien 
test2(int i,int j)558df257a6SAlex Richardson __attribute__((noinline)) void test2(int i, int j) {
568df257a6SAlex Richardson   fprintf(stderr, "starting %s\n", __func__);
577fab97f3SLogan Chien   backtrace(i);
587fab97f3SLogan Chien   test1(j);
598df257a6SAlex Richardson   fprintf(stderr, "finished %s\n", __func__); // ensure return address is saved
607fab97f3SLogan Chien }
617fab97f3SLogan Chien 
test3(int i,int j,int k)628df257a6SAlex Richardson __attribute__((noinline)) void test3(int i, int j, int k) {
638df257a6SAlex Richardson   fprintf(stderr, "starting %s\n", __func__);
647fab97f3SLogan Chien   backtrace(i);
657fab97f3SLogan Chien   test2(j, k);
668df257a6SAlex Richardson   fprintf(stderr, "finished %s\n", __func__); // ensure return address is saved
677fab97f3SLogan Chien }
687fab97f3SLogan Chien 
test_no_info()69ae685e7aSSaleem Abdulrasool void test_no_info() {
70ae685e7aSSaleem Abdulrasool   unw_context_t context;
71ae685e7aSSaleem Abdulrasool   unw_getcontext(&context);
72ae685e7aSSaleem Abdulrasool 
73ae685e7aSSaleem Abdulrasool   unw_cursor_t cursor;
74ae685e7aSSaleem Abdulrasool   unw_init_local(&cursor, &context);
75ae685e7aSSaleem Abdulrasool 
76ae685e7aSSaleem Abdulrasool   unw_proc_info_t info;
77ae685e7aSSaleem Abdulrasool   int ret = unw_get_proc_info(&cursor, &info);
78ae685e7aSSaleem Abdulrasool   if (ret != UNW_ESUCCESS)
79ae685e7aSSaleem Abdulrasool     abort();
80ae685e7aSSaleem Abdulrasool 
81ae685e7aSSaleem Abdulrasool   // Set the IP to an address clearly outside any function.
82b44204c7SJohn Brawn   unw_set_reg(&cursor, UNW_REG_IP, (unw_word_t)0);
83ae685e7aSSaleem Abdulrasool 
84ae685e7aSSaleem Abdulrasool   ret = unw_get_proc_info(&cursor, &info);
85ae685e7aSSaleem Abdulrasool   if (ret != UNW_ENOINFO)
86ae685e7aSSaleem Abdulrasool     abort();
87ae685e7aSSaleem Abdulrasool }
88ae685e7aSSaleem Abdulrasool 
test_reg_names()892f1ee56fSVitaly Buka void test_reg_names() {
902f1ee56fSVitaly Buka   unw_context_t context;
912f1ee56fSVitaly Buka   unw_getcontext(&context);
922f1ee56fSVitaly Buka 
932f1ee56fSVitaly Buka   unw_cursor_t cursor;
942f1ee56fSVitaly Buka   unw_init_local(&cursor, &context);
952f1ee56fSVitaly Buka 
962f1ee56fSVitaly Buka   int max_reg_num = -100;
972f1ee56fSVitaly Buka #if defined(__i386__)
982f1ee56fSVitaly Buka   max_reg_num = 7;
992f1ee56fSVitaly Buka #elif defined(__x86_64__)
1002f1ee56fSVitaly Buka   max_reg_num = 32;
1012f1ee56fSVitaly Buka #endif
1022f1ee56fSVitaly Buka 
1032f1ee56fSVitaly Buka   const char prefix[] = "unknown";
1042f1ee56fSVitaly Buka   for (int i = -2; i < max_reg_num; ++i) {
1052f1ee56fSVitaly Buka     if (strncmp(prefix, unw_regname(&cursor, i), sizeof(prefix) - 1) == 0)
1062f1ee56fSVitaly Buka       abort();
1072f1ee56fSVitaly Buka   }
1082f1ee56fSVitaly Buka 
1092f1ee56fSVitaly Buka   if (strncmp(prefix, unw_regname(&cursor, max_reg_num + 1),
1102f1ee56fSVitaly Buka               sizeof(prefix) - 1) != 0)
1112f1ee56fSVitaly Buka     abort();
1122f1ee56fSVitaly Buka }
1132f1ee56fSVitaly Buka 
1142f1ee56fSVitaly Buka #if defined(__x86_64__)
test_reg_get_set()1152f1ee56fSVitaly Buka void test_reg_get_set() {
1162f1ee56fSVitaly Buka   unw_context_t context;
1172f1ee56fSVitaly Buka   unw_getcontext(&context);
1182f1ee56fSVitaly Buka 
1192f1ee56fSVitaly Buka   unw_cursor_t cursor;
1202f1ee56fSVitaly Buka   unw_init_local(&cursor, &context);
1212f1ee56fSVitaly Buka 
1222f1ee56fSVitaly Buka   for (int i = 0; i < 17; ++i) {
1232f1ee56fSVitaly Buka     const unw_word_t set_value = 7;
1242f1ee56fSVitaly Buka     if (unw_set_reg(&cursor, i, set_value) != UNW_ESUCCESS)
1252f1ee56fSVitaly Buka       abort();
1262f1ee56fSVitaly Buka 
1272f1ee56fSVitaly Buka     unw_word_t get_value = 0;
1282f1ee56fSVitaly Buka     if (unw_get_reg(&cursor, i, &get_value) != UNW_ESUCCESS)
1292f1ee56fSVitaly Buka       abort();
1302f1ee56fSVitaly Buka 
1312f1ee56fSVitaly Buka     if (set_value != get_value)
1322f1ee56fSVitaly Buka       abort();
1332f1ee56fSVitaly Buka   }
1342f1ee56fSVitaly Buka }
1352f1ee56fSVitaly Buka 
test_fpreg_get_set()1362f1ee56fSVitaly Buka void test_fpreg_get_set() {
1372f1ee56fSVitaly Buka   unw_context_t context;
1382f1ee56fSVitaly Buka   unw_getcontext(&context);
1392f1ee56fSVitaly Buka 
1402f1ee56fSVitaly Buka   unw_cursor_t cursor;
1412f1ee56fSVitaly Buka   unw_init_local(&cursor, &context);
1422f1ee56fSVitaly Buka 
1432f1ee56fSVitaly Buka   // get/set is not implemented for x86_64 fpregs.
1442f1ee56fSVitaly Buka   for (int i = 17; i < 33; ++i) {
1452f1ee56fSVitaly Buka     const unw_fpreg_t set_value = 7;
1462f1ee56fSVitaly Buka     if (unw_set_fpreg(&cursor, i, set_value) != UNW_EBADREG)
1472f1ee56fSVitaly Buka       abort();
1482f1ee56fSVitaly Buka 
1492f1ee56fSVitaly Buka     unw_fpreg_t get_value = 0;
1502f1ee56fSVitaly Buka     if (unw_get_fpreg(&cursor, i, &get_value) != UNW_EBADREG)
1512f1ee56fSVitaly Buka       abort();
1522f1ee56fSVitaly Buka   }
1532f1ee56fSVitaly Buka }
1542f1ee56fSVitaly Buka #else
test_reg_get_set()1552f1ee56fSVitaly Buka void test_reg_get_set() {}
test_fpreg_get_set()1562f1ee56fSVitaly Buka void test_fpreg_get_set() {}
1572f1ee56fSVitaly Buka #endif
1582f1ee56fSVitaly Buka 
main(int,char **)159504bc07dSLouis Dionne int main(int, char**) {
1608df257a6SAlex Richardson   test1(3);
1618df257a6SAlex Richardson   test2(3, 4);
1628df257a6SAlex Richardson   test3(3, 4, 5);
163ae685e7aSSaleem Abdulrasool   test_no_info();
1642f1ee56fSVitaly Buka   test_reg_names();
1652f1ee56fSVitaly Buka   test_reg_get_set();
1662f1ee56fSVitaly Buka   test_fpreg_get_set();
167504bc07dSLouis Dionne   return 0;
1687fab97f3SLogan Chien }
169