Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h =================================================================== --- lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h +++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h @@ -69,6 +69,13 @@ uint32_t gdb_st_ctime; }; +enum GDBErrno { +#define HANDLE_ERRNO(name, value) GDB_##name = value, +#include "Plugins/Process/gdb-remote/GDBRemoteErrno.def" +#undef HANDLE_ERRNO + GDB_EUNKNOWN = 9999 +}; + class ProcessGDBRemote; class GDBRemoteCommunication : public Communication { Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp =================================================================== --- lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -3066,6 +3066,18 @@ return Status(response.GetHexMaxU32(false, UINT32_MAX), eErrorTypePOSIX); } +static int gdb_errno_to_system(int err) { + switch (err) { +#define HANDLE_ERRNO(name, value) \ + case GDB_##name: \ + return name; +#include "Plugins/Process/gdb-remote/GDBRemoteErrno.def" +#undef HANDLE_ERRNO + default: + return -1; + } +} + static uint64_t ParseHostIOPacketResponse(StringExtractorGDBRemote &response, uint64_t fail_result, Status &error) { response.SetFilePos(0); @@ -3075,8 +3087,8 @@ if (result == -2) return fail_result; if (response.GetChar() == ',') { - int result_errno = response.GetS32(-2, 16); - if (result_errno != -2) + int result_errno = gdb_errno_to_system(response.GetS32(-1, 16)); + if (result_errno != -1) error.SetError(result_errno, eErrorTypePOSIX); else error.SetError(-1, eErrorTypeGeneric); @@ -3246,7 +3258,7 @@ const uint32_t mode = response.GetS32(-1, 16); if (static_cast(mode) == -1) { if (response.GetChar() == ',') { - int response_errno = response.GetS32(-1, 16); + int response_errno = gdb_errno_to_system(response.GetS32(-1, 16)); if (response_errno > 0) error.SetError(response_errno, lldb::eErrorTypePOSIX); else @@ -3289,7 +3301,7 @@ if (retcode == -1) { error.SetErrorToGenericError(); if (response.GetChar() == ',') { - int response_errno = response.GetS32(-1, 16); + int response_errno = gdb_errno_to_system(response.GetS32(-1, 16)); if (response_errno > 0) error.SetError(response_errno, lldb::eErrorTypePOSIX); } @@ -3332,7 +3344,7 @@ if (bytes_written == -1) { error.SetErrorToGenericError(); if (response.GetChar() == ',') { - int response_errno = response.GetS32(-1, 16); + int response_errno = gdb_errno_to_system(response.GetS32(-1, 16)); if (response_errno > 0) error.SetError(response_errno, lldb::eErrorTypePOSIX); } @@ -3364,7 +3376,7 @@ if (result != 0) { error.SetErrorToGenericError(); if (response.GetChar() == ',') { - int response_errno = response.GetS32(-1, 16); + int response_errno = gdb_errno_to_system(response.GetS32(-1, 16)); if (response_errno > 0) error.SetError(response_errno, lldb::eErrorTypePOSIX); } @@ -3395,7 +3407,7 @@ if (result != 0) { error.SetErrorToGenericError(); if (response.GetChar() == ',') { - int response_errno = response.GetS32(-1, 16); + int response_errno = gdb_errno_to_system(response.GetS32(-1, 16)); if (response_errno > 0) error.SetError(response_errno, lldb::eErrorTypePOSIX); } Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp =================================================================== --- lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp +++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp @@ -535,6 +535,18 @@ return SendErrorResponse(18); } +static GDBErrno system_errno_to_gdb(int err) { + switch (err) { +#define HANDLE_ERRNO(name, value) \ + case name: \ + return GDB_##name; +#include "Plugins/Process/gdb-remote/GDBRemoteErrno.def" +#undef HANDLE_ERRNO + default: + return GDB_EUNKNOWN; + } +} + GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_vFile_Close( StringExtractorGDBRemote &packet) { @@ -554,7 +566,7 @@ response.PutChar('F'); response.Printf("%x", err); if (save_errno) - response.Printf(",%x", save_errno); + response.Printf(",%x", system_errno_to_gdb(save_errno)); return SendPacketNoLock(response.GetString()); } @@ -585,7 +597,7 @@ } else { response.PutCString("-1"); if (save_errno) - response.Printf(",%x", save_errno); + response.Printf(",%x", system_errno_to_gdb(save_errno)); } return SendPacketNoLock(response.GetString()); } @@ -617,7 +629,7 @@ else { response.PutCString("-1"); if (save_errno) - response.Printf(",%x", save_errno); + response.Printf(",%x", system_errno_to_gdb(save_errno)); } } else { response.Printf("-1,%x", EINVAL); @@ -769,7 +781,7 @@ struct stat file_stats; if (::fstat(fd, &file_stats) == -1) { const int save_errno = errno; - response.Printf("F-1,%x", save_errno); + response.Printf("F-1,%x", system_errno_to_gdb(save_errno)); return SendPacketNoLock(response.GetString()); } Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteErrno.def =================================================================== --- /dev/null +++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteErrno.def @@ -0,0 +1,37 @@ +//===-- GDBRemoteErrno.def --------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// NOTE: NO INCLUDE GUARD DESIRED! + +// HANDLE_ERRNO(name, value) +#ifndef HANDLE_ERRNO +#error "HANDLE_ERRNO must be defined" +#endif + +// from gdb's include/gdb/fileio.h +HANDLE_ERRNO(EPERM, 1) +HANDLE_ERRNO(ENOENT, 2) +HANDLE_ERRNO(EINTR, 4) +HANDLE_ERRNO(EIO, 5) +HANDLE_ERRNO(EBADF, 9) +HANDLE_ERRNO(EACCES, 13) +HANDLE_ERRNO(EFAULT, 14) +HANDLE_ERRNO(EBUSY, 16) +HANDLE_ERRNO(EEXIST, 17) +HANDLE_ERRNO(ENODEV, 19) +HANDLE_ERRNO(ENOTDIR, 20) +HANDLE_ERRNO(EISDIR, 21) +HANDLE_ERRNO(EINVAL, 22) +HANDLE_ERRNO(ENFILE, 23) +HANDLE_ERRNO(EMFILE, 24) +HANDLE_ERRNO(EFBIG, 27) +HANDLE_ERRNO(ENOSPC, 28) +HANDLE_ERRNO(ESPIPE, 29) +HANDLE_ERRNO(EROFS, 30) +HANDLE_ERRNO(ENOSYS, 88) +HANDLE_ERRNO(ENAMETOOLONG, 91) Index: lldb/test/API/functionalities/gdb_remote_client/TestGDBRemotePlatformFile.py =================================================================== --- lldb/test/API/functionalities/gdb_remote_client/TestGDBRemotePlatformFile.py +++ lldb/test/API/functionalities/gdb_remote_client/TestGDBRemotePlatformFile.py @@ -15,7 +15,7 @@ return "Fa" elif packet.startswith("vFile:close:"): return "F0" - return "F-1,16" + return "F-1,58" self.server.responder = Responder() @@ -47,7 +47,9 @@ class Responder(MockGDBServerResponder): def vFile(self, packet): - return "F-1,16" + # use ENOSYS as this constant differs between GDB Remote + # Protocol and Linux, so we can test the translation + return "F-1,58" self.server.responder = Responder() @@ -58,16 +60,16 @@ self.assertTrue(self.dbg.GetSelectedPlatform().IsConnected()) self.match("platform file open /some/file.txt -v 0755", - [r"error: Invalid argument"], + [r"error: Function not implemented"], error=True) self.match("platform file read 16 -o 11 -c 13", - [r"error: Invalid argument"], + [r"error: Function not implemented"], error=True) self.match("platform file write 16 -o 11 -d teststring", - [r"error: Invalid argument"], + [r"error: Function not implemented"], error=True) self.match("platform file close 16", - [r"error: Invalid argument"], + [r"error: Function not implemented"], error=True) self.assertPacketLogContains([ "vFile:open:2f736f6d652f66696c652e747874,00000202,000001ed",