qemu-user uses fixed stack size and ignores RLIMIT_STACK request, causing some guest programs to crash
Host environment
- Operating system: Arch Linux
- OS/kernel version: Linux 6.4.12-arch1-1 #1 SMP PREEMPT_DYNAMIC Thu, 24 Aug 2023 00:38:14 +0000 x86_64 GNU/Linux
- Architecture: x86_64
- QEMU flavor: qemu-riscv64-static
- QEMU version: qemu-riscv64 version 8.1.0
- QEMU command line: (Unfortunately, it is hard for me to provide a single commandline that exhibits the problem)
Emulated/Virtualized environment
- Operating system: Arch Linux riscv64
- OS/kernel version: Linux 6.4.12-arch1-1 #1 SMP PREEMPT_DYNAMIC Thu, 24 Aug 2023 00:38:14 +0000 riscv64 GNU/Linux
- Architecture: riscv64
Description of problem
When compiling a source file, g++ segmentation faults in qemu-user riscv64. But it doesn't fail on real riscv64 boards.
We discovered this problem while compiling nodejs-lts-hydrogen. The source file has been reduced to 5KB by cvise.
Steps to reproduce
- Setup an Arch Linux riscv64 qemu-user container: https://github.com/felixonmars/archriscv-packages/wiki/Setup-Arch-Linux-RISC-V-Development-Environment
- Start the container:
sudo systemd-nspawn -D ./archriscv -a -U
- Install gcc inside the container:
sudo pacman -Syu gcc
- Run the following command in the container:
g++ -S testcase.i -w -fpreprocessed -o /dev/null
testcase.i - g++ segmentation faults:
g++: internal compiler error: Segmentation fault signal terminated program cc1plus
Additional information
Initially I thought this is a g++ bug. But I can't reproduce this bug on real riscv64 hardware.
g++ version: g++ (GCC) 13.2.1 20230801
testcase.i:
namespace std {
typedef long unsigned size_t;
inline namespace __cxx11 {}
} // namespace std
typedef char uint8_t;
namespace std {
template <typename _Default, typename, template <typename> class>
struct __detector {
using type = _Default;
};
template <typename _Default, template <typename> class _Op>
using __detected_or = __detector<_Default, void, _Op>;
template <typename _Default, template <typename> class _Op>
using __detected_or_t = typename __detected_or<_Default, _Op>::type;
template <typename> class allocator;
namespace __cxx11 {
template <typename _CharT, typename = _CharT, typename = allocator<_CharT>>
class basic_string;
}
typedef basic_string<char> string;
} // namespace std
template <typename _Tp> class __new_allocator {
public:
typedef _Tp value_type;
};
namespace std {
template <typename _Tp> using __allocator_base = __new_allocator<_Tp>;
template <typename _Tp> class allocator : public __allocator_base<_Tp> {};
template <class _E> class initializer_list {
typedef size_t size_type;
typedef _E *iterator;
iterator _M_array;
size_type _M_len;
};
struct __allocator_traits_base {
template <typename _Tp> using __pointer = typename _Tp::const_pointer;
};
template <typename _Alloc> struct allocator_traits : __allocator_traits_base {
typedef typename _Alloc::value_type value_type;
using pointer = __detected_or_t<value_type, __pointer>;
};
} // namespace std
namespace __gnu_cxx {
template <typename _Alloc>
struct __alloc_traits : std::allocator_traits<_Alloc> {};
} // namespace __gnu_cxx
namespace std {
namespace __cxx11 {
template <typename _CharT, typename, typename _Alloc> class basic_string {
typedef __gnu_cxx::__alloc_traits<_Alloc> _Alloc_traits;
public:
typedef typename _Alloc_traits::pointer pointer;
struct _Alloc_hider {
_Alloc_hider(pointer, _Alloc);
} _M_dataplus;
pointer _M_local_data();
basic_string(_CharT *, _Alloc __a = _Alloc())
: _M_dataplus(_M_local_data(), __a) {}
~basic_string();
};
} // namespace __cxx11
} // namespace std
namespace v8 {
class StartupData {};
} // namespace v8
namespace std {
template <typename _Tp> class vector {
public:
typedef _Tp value_type;
vector(initializer_list<value_type>);
};
namespace builtins {
struct CodeCacheInfo {
string id;
vector<uint8_t> data;
};
} // namespace builtins
struct IsolateDataSerializeInfo {};
struct EnvSerializeInfo {};
struct SnapshotMetadata {
enum { kDefault } type;
string node_version;
string node_arch;
string v8_cache_version_tag;
};
struct SnapshotData {
enum { kNotOwned } data_ownership;
SnapshotMetadata metadata;
v8::StartupData v8_snapshot_blob_data;
IsolateDataSerializeInfo isolate_data_info;
EnvSerializeInfo env_info;
vector<builtins::CodeCacheInfo> code_cache;
} snapshot_data{
SnapshotData::kNotOwned,
SnapshotMetadata::kDefault,
"",
"",
"",
{},
{},
{},
{{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}}};
} // namespace std