Skip to content

Commit 9434690

Browse files
committedJan 3, 2017
Simplify reading of Linux notes to correctly handle endianess.
Summary: This patch changes and simplifies the way notes are read from Linux Elf cores. The current implementation copies the bytes from the notes directly over the lldb structure for 64 bit cores and reads field by field for 32 bit cores. Reading the bytes directly only works if the endianess of the core dump and the platform that lldb are running on matches. The case statements for s390x and x86_64 would would only work on big endian systems and little endian systems respectively. That meant that x86_64 generally worked but s390x didn't unless you were on s390x or another big endian platform. This patch just reads field by field on all platform and updates the field by field version to allow for those fields which are word size instead of fixed size. It should also slightly simplify adding support for a new Linux platform. This patch also re-enables the s390x test case in TestLinuxCore.py on all non-s390x platforms as it now passes. Reviewers: uweigand, clayborg Differential Revision: https://reviews.llvm.org/D27571 llvm-svn: 290874
1 parent 3626516 commit 9434690

File tree

2 files changed

+58
-103
lines changed

2 files changed

+58
-103
lines changed
 

‎lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/TestLinuxCore.py

+1-3
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,7 @@ def test_x86_64(self):
3838
"""Test that lldb can read the process information from an x86_64 linux core file."""
3939
self.do_test("linux-x86_64", self._x86_64_pid, self._x86_64_regions)
4040

41-
# This seems to hang on non-s390x platforms for some reason. Disabling
42-
# for now.
43-
@skipIf(archs=no_match(['s390x']))
41+
@skipIf(oslist=['windows'])
4442
@skipIf(triple='^mips')
4543
def test_s390x(self):
4644
"""Test that lldb can read the process information from an s390x linux core file."""

‎lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp

+57-100
Original file line numberDiff line numberDiff line change
@@ -202,58 +202,43 @@ ELFLinuxPrStatus::ELFLinuxPrStatus() {
202202

203203
Error ELFLinuxPrStatus::Parse(DataExtractor &data, ArchSpec &arch) {
204204
Error error;
205-
ByteOrder byteorder = data.GetByteOrder();
206205
if (GetSize(arch) > data.GetByteSize()) {
207206
error.SetErrorStringWithFormat(
208207
"NT_PRSTATUS size should be %zu, but the remaining bytes are: %" PRIu64,
209208
GetSize(arch), data.GetByteSize());
210209
return error;
211210
}
212211

213-
switch (arch.GetCore()) {
214-
case ArchSpec::eCore_s390x_generic:
215-
case ArchSpec::eCore_x86_64_x86_64:
216-
data.ExtractBytes(0, sizeof(ELFLinuxPrStatus), byteorder, this);
217-
break;
218-
case ArchSpec::eCore_x86_32_i386:
219-
case ArchSpec::eCore_x86_32_i486: {
220-
// Parsing from a 32 bit ELF core file, and populating/reusing the structure
221-
// properly, because the struct is for the 64 bit version
222-
offset_t offset = 0;
223-
si_signo = data.GetU32(&offset);
224-
si_code = data.GetU32(&offset);
225-
si_errno = data.GetU32(&offset);
212+
// Read field by field to correctly account for endianess
213+
// of both the core dump and the platform running lldb.
214+
offset_t offset = 0;
215+
si_signo = data.GetU32(&offset);
216+
si_code = data.GetU32(&offset);
217+
si_errno = data.GetU32(&offset);
226218

227-
pr_cursig = data.GetU16(&offset);
228-
offset += 2; // pad
219+
pr_cursig = data.GetU16(&offset);
220+
offset += 2; // pad
229221

230-
pr_sigpend = data.GetU32(&offset);
231-
pr_sighold = data.GetU32(&offset);
222+
pr_sigpend = data.GetPointer(&offset);
223+
pr_sighold = data.GetPointer(&offset);
232224

233-
pr_pid = data.GetU32(&offset);
234-
pr_ppid = data.GetU32(&offset);
235-
pr_pgrp = data.GetU32(&offset);
236-
pr_sid = data.GetU32(&offset);
225+
pr_pid = data.GetU32(&offset);
226+
pr_ppid = data.GetU32(&offset);
227+
pr_pgrp = data.GetU32(&offset);
228+
pr_sid = data.GetU32(&offset);
237229

238-
pr_utime.tv_sec = data.GetU32(&offset);
239-
pr_utime.tv_usec = data.GetU32(&offset);
230+
pr_utime.tv_sec = data.GetPointer(&offset);
231+
pr_utime.tv_usec = data.GetPointer(&offset);
240232

241-
pr_stime.tv_sec = data.GetU32(&offset);
242-
pr_stime.tv_usec = data.GetU32(&offset);
233+
pr_stime.tv_sec = data.GetPointer(&offset);
234+
pr_stime.tv_usec = data.GetPointer(&offset);
243235

244-
pr_cutime.tv_sec = data.GetU32(&offset);
245-
pr_cutime.tv_usec = data.GetU32(&offset);
236+
pr_cutime.tv_sec = data.GetPointer(&offset);
237+
pr_cutime.tv_usec = data.GetPointer(&offset);
246238

247-
pr_cstime.tv_sec = data.GetU32(&offset);
248-
pr_cstime.tv_usec = data.GetU32(&offset);
239+
pr_cstime.tv_sec = data.GetPointer(&offset);
240+
pr_cstime.tv_usec = data.GetPointer(&offset);
249241

250-
break;
251-
}
252-
default:
253-
error.SetErrorStringWithFormat("ELFLinuxPrStatus::%s Unknown architecture",
254-
__FUNCTION__);
255-
break;
256-
}
257242

258243
return error;
259244
}
@@ -274,49 +259,37 @@ Error ELFLinuxPrPsInfo::Parse(DataExtractor &data, ArchSpec &arch) {
274259
GetSize(arch), data.GetByteSize());
275260
return error;
276261
}
277-
278-
switch (arch.GetCore()) {
279-
case ArchSpec::eCore_s390x_generic:
280-
case ArchSpec::eCore_x86_64_x86_64:
281-
data.ExtractBytes(0, sizeof(ELFLinuxPrPsInfo), byteorder, this);
282-
break;
283-
case ArchSpec::eCore_x86_32_i386:
284-
case ArchSpec::eCore_x86_32_i486: {
285-
// Parsing from a 32 bit ELF core file, and populating/reusing the structure
286-
// properly, because the struct is for the 64 bit version
287-
size_t size = 0;
288-
offset_t offset = 0;
289-
290-
pr_state = data.GetU8(&offset);
291-
pr_sname = data.GetU8(&offset);
292-
pr_zomb = data.GetU8(&offset);
293-
pr_nice = data.GetU8(&offset);
294-
295-
pr_flag = data.GetU32(&offset);
296-
pr_uid = data.GetU16(&offset);
297-
pr_gid = data.GetU16(&offset);
298-
299-
pr_pid = data.GetU32(&offset);
300-
pr_ppid = data.GetU32(&offset);
301-
pr_pgrp = data.GetU32(&offset);
302-
pr_sid = data.GetU32(&offset);
303-
304-
size = 16;
305-
data.ExtractBytes(offset, size, byteorder, pr_fname);
306-
offset += size;
307-
308-
size = 80;
309-
data.ExtractBytes(offset, size, byteorder, pr_psargs);
310-
offset += size;
311-
312-
break;
313-
}
314-
default:
315-
error.SetErrorStringWithFormat("ELFLinuxPrPsInfo::%s Unknown architecture",
316-
__FUNCTION__);
317-
break;
262+
size_t size = 0;
263+
offset_t offset = 0;
264+
265+
pr_state = data.GetU8(&offset);
266+
pr_sname = data.GetU8(&offset);
267+
pr_zomb = data.GetU8(&offset);
268+
pr_nice = data.GetU8(&offset);
269+
if (data.GetAddressByteSize() == 8) {
270+
// Word align the next field on 64 bit.
271+
offset += 4;
318272
}
319273

274+
pr_flag = data.GetPointer(&offset);
275+
276+
// 16 bit on 32 bit platforms, 32 bit on 64 bit platforms
277+
pr_uid = data.GetMaxU64(&offset, data.GetAddressByteSize() >> 1);
278+
pr_gid = data.GetMaxU64(&offset, data.GetAddressByteSize() >> 1);
279+
280+
pr_pid = data.GetU32(&offset);
281+
pr_ppid = data.GetU32(&offset);
282+
pr_pgrp = data.GetU32(&offset);
283+
pr_sid = data.GetU32(&offset);
284+
285+
size = 16;
286+
data.ExtractBytes(offset, size, byteorder, pr_fname);
287+
offset += size;
288+
289+
size = 80;
290+
data.ExtractBytes(offset, size, byteorder, pr_psargs);
291+
offset += size;
292+
320293
return error;
321294
}
322295

@@ -329,35 +302,19 @@ ELFLinuxSigInfo::ELFLinuxSigInfo() {
329302

330303
Error ELFLinuxSigInfo::Parse(DataExtractor &data, const ArchSpec &arch) {
331304
Error error;
332-
ByteOrder byteorder = data.GetByteOrder();
333305
if (GetSize(arch) > data.GetByteSize()) {
334306
error.SetErrorStringWithFormat(
335307
"NT_SIGINFO size should be %zu, but the remaining bytes are: %" PRIu64,
336308
GetSize(arch), data.GetByteSize());
337309
return error;
338310
}
339311

340-
switch (arch.GetCore()) {
341-
case ArchSpec::eCore_x86_64_x86_64:
342-
data.ExtractBytes(0, sizeof(ELFLinuxPrStatus), byteorder, this);
343-
break;
344-
case ArchSpec::eCore_s390x_generic:
345-
case ArchSpec::eCore_x86_32_i386:
346-
case ArchSpec::eCore_x86_32_i486: {
347-
// Parsing from a 32 bit ELF core file, and populating/reusing the structure
348-
// properly, because the struct is for the 64 bit version
349-
offset_t offset = 0;
350-
si_signo = data.GetU32(&offset);
351-
si_code = data.GetU32(&offset);
352-
si_errno = data.GetU32(&offset);
353-
354-
break;
355-
}
356-
default:
357-
error.SetErrorStringWithFormat("ELFLinuxSigInfo::%s Unknown architecture",
358-
__FUNCTION__);
359-
break;
360-
}
312+
// Parsing from a 32 bit ELF core file, and populating/reusing the structure
313+
// properly, because the struct is for the 64 bit version
314+
offset_t offset = 0;
315+
si_signo = data.GetU32(&offset);
316+
si_code = data.GetU32(&offset);
317+
si_errno = data.GetU32(&offset);
361318

362319
return error;
363320
}

0 commit comments

Comments
 (0)
Please sign in to comment.