Index: llvm/test/tools/llvm-readobj/ELF/mips-options-sec.test =================================================================== --- llvm/test/tools/llvm-readobj/ELF/mips-options-sec.test +++ llvm/test/tools/llvm-readobj/ELF/mips-options-sec.test @@ -1,14 +1,96 @@ ## Check that we are able to dump the SHT_MIPS_OPTIONS section using -A properly. -# RUN: llvm-readobj -A %p/Inputs/options.obj.elf-mipsel | FileCheck %s +## Check we are able to dump multiple MIPS options properly. +# RUN: yaml2obj %s -o %t1 +# RUN: llvm-readobj -A %t1 | FileCheck %s +# RUN: llvm-readelf -A %t1 | FileCheck %s # CHECK: MIPS Options { # CHECK-NEXT: ODK_REGINFO { +# CHECK-NEXT: GP: 0x807060504030201 +# CHECK-NEXT: General Mask: 0xD0C0B0A +# CHECK-NEXT: Co-Proc Mask0: 0x88776655 +# CHECK-NEXT: Co-Proc Mask1: 0xCCBBAA99 +# CHECK-NEXT: Co-Proc Mask2: 0x1EFFEEDD +# CHECK-NEXT: Co-Proc Mask3: 0x5E4E3E2E +# CHECK-NEXT: } +# CHECK-NEXT: ODK_REGINFO { # CHECK-NEXT: GP: 0x0 -# CHECK-NEXT: General Mask: 0xF2000017 +# CHECK-NEXT: General Mask: 0x0 # CHECK-NEXT: Co-Proc Mask0: 0x0 # CHECK-NEXT: Co-Proc Mask1: 0x0 # CHECK-NEXT: Co-Proc Mask2: 0x0 # CHECK-NEXT: Co-Proc Mask3: 0x0 # CHECK-NEXT: } # CHECK-NEXT: } + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_MIPS +Sections: + - Name: .MIPS.options + Type: SHT_MIPS_OPTIONS + ShSize: [[SECSIZE=]] + ContentArray: [ [[KIND=0x1]], ## Kind. ODK_REGINFO == 1. + [[DESCSIZE=0x28]], ## Byte size of descriptor, including this header. + 0x0, 0x0, ## Section header index of section affected or 0 for global options. + 0x0, 0x0, 0x0, 0x0, ## Kind-specific information. + 0xA, 0xB, 0xC, 0xD, ## ODK_REGINFO: bit-mask of used general registers. + 0x11, 0x22, 0x33, 0x44, ## ODK_REGINFO: unused padding field. + 0x55, 0x66, 0x77, 0x88, ## ODK_REGINFO: bit-mask of used co-processor registers (0). + 0x99, 0xAA, 0xBB, 0xCC, ## ODK_REGINFO: bit-mask of used co-processor registers (1). + 0xDD, 0xEE, 0xFF, 0x1E, ## ODK_REGINFO: bit-mask of used co-processor registers (2). + 0x2E, 0x3E, 0x4E, 0x5E, ## ODK_REGINFO: bit-mask of used co-processor registers (3). + 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, ## ODK_REGINFO: gp register value. +## A descriptor for a one more arbirtary supported option. + 0x1, 0x28, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ] + +## Check we report a warning when the .MIPS.options section has a size that is less than the +## size of the .MIPS.options description header. + +# RUN: yaml2obj %s -DSECSIZE=0x1 -o %t2 +# RUN: llvm-readobj -A %t2 2>&1 | FileCheck %s -DFILE=%t2 --check-prefix=SEC-SIZE +# RUN: llvm-readelf -A %t2 2>&1 | FileCheck %s -DFILE=%t2 --check-prefix=SEC-SIZE + +# SEC-SIZE: MIPS Options { +# SEC-SIZE-NEXT: warning: '[[FILE]]': the .MIPS.options section has a wrong size (0x1) +# SEC-SIZE-NEXT: } + +## Check we report a warning when the .MIPS.options description header has a size +## that goes past the end of the section. + +# RUN: yaml2obj %s -DDESCSIZE=0x51 -o %t3 +# RUN: llvm-readobj -A %t3 2>&1 | FileCheck %s -DFILE=%t3 --check-prefix=DESC-SIZE +# RUN: llvm-readelf -A %t3 2>&1 | FileCheck %s -DFILE=%t3 --check-prefix=DESC-SIZE + +# DESC-SIZE: IPS Options { +# DESC-SIZE-NEXT: warning: '[[FILE]]': the descriptior of size 0x51 goes past the end of the .MIPS.options section of size 0x50 +# DESC-SIZE-NEXT: } + +## Check we are able to skip unsupported options and continue dumping. + +# RUN: yaml2obj %s -DKIND=0x2 -o %t4 +# RUN: llvm-readobj -A %t4 2>&1 | FileCheck %s -DFILE=%t4 -DTAG="ODK_EXCEPTIONS (2)" --check-prefix=KIND +# RUN: llvm-readobj -A %t4 2>&1 | FileCheck %s -DFILE=%t4 -DTAG="ODK_EXCEPTIONS (2)" --check-prefix=KIND + +# RUN: yaml2obj %s -DKIND=0xFF -o %t5 +# RUN: llvm-readobj -A %t5 2>&1 | FileCheck %s -DFILE=%t5 -DTAG="Unknown (255)" --check-prefix=KIND +# RUN: llvm-readobj -A %t5 2>&1 | FileCheck %s -DFILE=%t5 -DTAG="Unknown (255)" --check-prefix=KIND + +# KIND: MIPS Options { +# KIND-NEXT: Unsupported MIPS options tag: [[TAG]] +# KIND-NEXT: ODK_REGINFO { +# KIND-NEXT: GP: 0x0 +# KIND-NEXT: General Mask: 0x0 +# KIND-NEXT: Co-Proc Mask0: 0x0 +# KIND-NEXT: Co-Proc Mask1: 0x0 +# KIND-NEXT: Co-Proc Mask2: 0x0 +# KIND-NEXT: Co-Proc Mask3: 0x0 +# KIND-NEXT: } +# KIND-NEXT: } Index: llvm/tools/llvm-readobj/ELFDumper.cpp =================================================================== --- llvm/tools/llvm-readobj/ELFDumper.cpp +++ llvm/tools/llvm-readobj/ELFDumper.cpp @@ -3335,6 +3335,36 @@ printMipsReginfoData(W, *Reginfo); } +template +static Expected *> +readMipsOptions(ArrayRef &From, bool &IsSupported) { + if (From.size() < sizeof(Elf_Mips_Options)) + return createError("the .MIPS.options section has a wrong size (0x" + + Twine::utohexstr(From.size()) + ")"); + + auto *O = reinterpret_cast *>(From.data()); + if (O->size > From.size()) + return createError( + "the descriptior of size 0x" + Twine::utohexstr(O->size) + + " goes past the end of the .MIPS.options section of size 0x" + + Twine::utohexstr(From.size())); + + IsSupported = O->kind == ODK_REGINFO; + size_t ExpectedSize = + sizeof(Elf_Mips_Options) + sizeof(Elf_Mips_RegInfo); + + if (IsSupported) + if (O->size < ExpectedSize) + return createError( + "the .MIPS.options section of kind " + + Twine(getElfMipsOptionsOdkType(O->kind)) + " has a wrong size (0x" + + Twine::utohexstr(From.size()) + "), the expected size is 0x" + + Twine::utohexstr(ExpectedSize)); + + From = From.drop_front(O->size); + return O; +} + template void ELFDumper::printMipsOptions() { const ELFFile *Obj = ObjF->getELFFile(); const Elf_Shdr *Shdr = @@ -3349,21 +3379,27 @@ ArrayRef Sec = unwrapOrError(ObjF->getFileName(), Obj->getSectionContents(Shdr)); while (!Sec.empty()) { - if (Sec.size() < sizeof(Elf_Mips_Options)) { - W.startLine() << "The .MIPS.options section has a wrong size.\n"; - return; - } - auto *O = reinterpret_cast *>(Sec.data()); - DictScope GS(W, getElfMipsOptionsOdkType(O->kind)); - switch (O->kind) { - case ODK_REGINFO: - printMipsReginfoData(W, O->getRegInfo()); - break; - default: - W.startLine() << "Unsupported MIPS options tag.\n"; + bool IsSupported; + Expected *> OptsOrErr = + readMipsOptions(Sec, IsSupported); + if (!OptsOrErr) { + reportUniqueWarning(OptsOrErr.takeError()); break; } - Sec = Sec.slice(O->size); + + unsigned Kind = (*OptsOrErr)->kind; + const char *Type = getElfMipsOptionsOdkType(Kind); + if (!IsSupported) { + W.startLine() << "Unsupported MIPS options tag: " << Type << " (" << Kind + << ")\n"; + continue; + } + + DictScope GS(W, Type); + if (Kind == ODK_REGINFO) + printMipsReginfoData(W, (*OptsOrErr)->getRegInfo()); + else + llvm_unreachable("unexpected .MIPS.options section descriptor kind"); } }