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,32 @@ uint32_t gdb_st_ctime; }; +// from gdb's include/gdb/fileio.h +enum GDBErrno { + GDB_EPERM = 1, + GDB_ENOENT = 2, + GDB_EINTR = 4, + GDB_EIO = 5, + GDB_EBADF = 9, + GDB_EACCES = 13, + GDB_EFAULT = 14, + GDB_EBUSY = 16, + GDB_EEXIST = 17, + GDB_ENODEV = 19, + GDB_ENOTDIR = 20, + GDB_EISDIR = 21, + GDB_EINVAL = 22, + GDB_ENFILE = 23, + GDB_EMFILE = 24, + GDB_EFBIG = 27, + GDB_ENOSPC = 28, + GDB_ESPIPE = 29, + GDB_EROFS = 30, + GDB_ENOSYS = 88, + GDB_ENAMETOOLONG = 91, + 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 @@ -3046,6 +3046,55 @@ return Status(response.GetHexMaxU32(false, UINT32_MAX), eErrorTypePOSIX); } +static int gdb_errno_to_system(int err) { + switch (err) { + case GDB_EPERM: + return EPERM; + case GDB_ENOENT: + return ENOENT; + case GDB_EINTR: + return EINTR; + case GDB_EIO: + return EIO; + case GDB_EBADF: + return EBADF; + case GDB_EACCES: + return EACCES; + case GDB_EFAULT: + return EFAULT; + case GDB_EBUSY: + return EBUSY; + case GDB_EEXIST: + return EEXIST; + case GDB_ENODEV: + return ENODEV; + case GDB_ENOTDIR: + return ENOTDIR; + case GDB_EISDIR: + return EISDIR; + case GDB_EINVAL: + return EINVAL; + case GDB_ENFILE: + return ENFILE; + case GDB_EMFILE: + return EMFILE; + case GDB_EFBIG: + return EFBIG; + case GDB_ENOSPC: + return ENOSPC; + case GDB_ESPIPE: + return ESPIPE; + case GDB_EROFS: + return EROFS; + case GDB_ENOSYS: + return ENOSYS; + case GDB_ENAMETOOLONG: + return ENAMETOOLONG; + default: + return -1; + } +} + static uint64_t ParseHostIOPacketResponse(StringExtractorGDBRemote &response, uint64_t fail_result, Status &error) { response.SetFilePos(0); @@ -3055,8 +3104,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); @@ -3225,7 +3274,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 @@ -3267,7 +3316,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); } @@ -3310,7 +3359,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); } @@ -3342,7 +3391,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); } @@ -3373,7 +3422,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,55 @@ return SendErrorResponse(18); } +static GDBErrno system_errno_to_gdb(int err) { + switch (err) { + case EPERM: + return GDB_EPERM; + case ENOENT: + return GDB_ENOENT; + case EINTR: + return GDB_EINTR; + case EIO: + return GDB_EIO; + case EBADF: + return GDB_EBADF; + case EACCES: + return GDB_EACCES; + case EFAULT: + return GDB_EFAULT; + case EBUSY: + return GDB_EBUSY; + case EEXIST: + return GDB_EEXIST; + case ENODEV: + return GDB_ENODEV; + case ENOTDIR: + return GDB_ENOTDIR; + case EISDIR: + return GDB_EISDIR; + case EINVAL: + return GDB_EINVAL; + case ENFILE: + return GDB_ENFILE; + case EMFILE: + return GDB_EMFILE; + case EFBIG: + return GDB_EFBIG; + case ENOSPC: + return GDB_ENOSPC; + case ESPIPE: + return GDB_ESPIPE; + case EROFS: + return GDB_EROFS; + case ENOSYS: + return GDB_ENOSYS; + case ENAMETOOLONG: + return GDB_ENAMETOOLONG; + default: + return GDB_EUNKNOWN; + } +} + GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_vFile_Close( StringExtractorGDBRemote &packet) { @@ -554,7 +603,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 +634,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 +666,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 +818,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/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",