31 if (DwarfVersion <= 4)
58 if (Form == dwarf::DW_FORM_string)
59 return InfoData.
getCStr(&InfoOffset);
62 case dwarf::DW_FORM_strx1:
63 StrIndex = InfoData.
getU8(&InfoOffset);
65 case dwarf::DW_FORM_strx2:
66 StrIndex = InfoData.
getU16(&InfoOffset);
68 case dwarf::DW_FORM_strx3:
69 StrIndex = InfoData.
getU24(&InfoOffset);
71 case dwarf::DW_FORM_strx4:
72 StrIndex = InfoData.
getU32(&InfoOffset);
74 case dwarf::DW_FORM_strx:
75 case dwarf::DW_FORM_GNU_str_index:
80 "string field must be encoded with one of the following: "
81 "DW_FORM_string, DW_FORM_strx, DW_FORM_strx1, DW_FORM_strx2, "
82 "DW_FORM_strx3, DW_FORM_strx4, or DW_FORM_GNU_str_index.");
85 uint64_t StrOffsetsOffset = 4 * StrIndex;
90 return StrData.
getCStr(&StrOffset);
98 if (Header.Version >= 5 && Header.UnitType != dwarf::DW_UT_split_compile)
100 std::string(
"unit type DW_UT_split_compile type not found in "
101 "debug_info header. Unexpected unit type 0x" +
102 utostr(Header.UnitType) +
" found"));
110 if (Tag != dwarf::DW_TAG_compile_unit)
113 AbbrevData.
getU8(&AbbrevOffset);
116 while ((Name = AbbrevData.
getULEB128(&AbbrevOffset)) |
119 (Name != 0 || Form != 0)) {
121 case dwarf::DW_AT_name: {
123 Form, InfoData,
Offset, StrOffsets, Str, Header.Version);
129 case dwarf::DW_AT_GNU_dwo_name:
130 case dwarf::DW_AT_dwo_name: {
132 Form, InfoData,
Offset, StrOffsets, Str, Header.Version);
138 case dwarf::DW_AT_GNU_dwo_id:
147 if (!Header.Signature)
149 ID.Signature = *Header.Signature;
168 return Index + DW_SECT_INFO;
174 const auto *Off = Entry.getContribution(
Kind);
177 return Section.substr(Off->getOffset(), Off->getLength());
184 bool &AnySectionOverflow) {
187 Twine(
" Section Contribution Offset overflow 4G. Previous Offset ") +
188 Twine(PrevOffset) +
Twine(
", After overflow offset ") +
195 AnySectionOverflow =
true;
207 bool &AnySectionOverflow) {
210 auto *
I =
E.getContributions();
213 auto P = TypeIndexEntries.
insert(std::make_pair(
E.getSignature(), TUEntry));
216 auto &Entry =
P.first->second;
218 Entry.Contributions[0] = {};
224 C.setOffset(
C.getOffset() +
I->getOffset());
225 C.setLength(
I->getLength());
228 auto &
C = Entry.Contributions[TypesContributionIndex];
233 C.setOffset(TypesOffset);
235 static_assert(
sizeof(OldOffset) ==
sizeof(TypesOffset));
236 TypesOffset +=
C.getLength();
237 if (OldOffset > TypesOffset) {
239 "Types", OverflowOptValue,
242 if (AnySectionOverflow) {
243 TypesOffset = OldOffset;
253 MCSection *OutputTypes,
const std::vector<StringRef> &TypesSections,
265 C.setOffset(TypesOffset);
274 Offset = PrevOffset +
C.getLength32();
276 auto P = TypeIndexEntries.
insert(std::make_pair(Signature, Entry));
280 Out.
emitBytes(Types.substr(PrevOffset,
C.getLength32()));
282 TypesOffset +=
C.getLength32();
283 if (OldOffset > TypesOffset) {
285 "Types", OverflowOptValue,
288 if (AnySectionOverflow) {
289 TypesOffset = OldOffset;
300 std::string Text =
"\'";
303 bool HasDWO = !DWOName.
empty();
304 bool HasDWP = !DWPName.
empty();
305 if (HasDWO || HasDWP) {
312 if (HasDWO && HasDWP)
314 if (!DWPName.
empty()) {
326 (
"failure while decompressing compressed section: '" + Name +
"', " +
346 UncompressedSections.emplace_back();
347 if (
Error E = Dec->resizeAndDecompress(UncompressedSections.back()))
350 Contents = UncompressedSections.
back();
361 std::tie(Header.Length, Header.Format) =
369 "compile unit exceeds .debug_info section range: " +
379 if (Header.Version >= 5) {
382 MinHeaderLength = 16;
387 if (Header.Length < MinHeaderLength) {
389 utostr(MinHeaderLength) +
" got " +
390 utostr(Header.Length) +
".");
392 if (Header.Version >= 5) {
397 if (Header.UnitType == dwarf::DW_UT_split_type) {
399 MinHeaderLength += 4;
400 if (Header.Length < MinHeaderLength)
411 Header.HeaderSize =
Offset;
424 const uint64_t NewOffset = OffsetRemapping[OldOffset];
427 Out.
emitIntValue(NewOffset & NewOffsetMask, NewOffsetSize);
438 if (CurStrSection.
empty() || CurStrOffsetSection.
empty())
454 while (
const char *S =
Data.getCStr(&LocalOffset)) {
456 OffsetRemapping[PrevOffset] = NewOffset;
459 NewOffset > UINT32_MAX) {
462 PrevOffset = LocalOffset;
475 "StrOffsetSection size is less than its header");
480 if (HeaderSize == 8) {
481 ContributionSize =
Data.getU32(&HeaderLengthOffset);
482 }
else if (HeaderSize == 16) {
484 HeaderLengthOffset += 4;
485 ContributionSize =
Data.getU64(&HeaderLengthOffset);
487 ContributionEnd = ContributionSize + HeaderLengthOffset;
490 if (OldOffsetSize == 4 && NewOffsetSize == 8) {
500 (ContributionSize - VersionPadSize) * 2 + VersionPadSize;
511 for (
auto &Pair : SectionLength) {
512 if (Pair.first == DW_SECT_STR_OFFSETS) {
513 Pair.second = NewLength + 12;
522 OldOffsetSize, NewOffsetSize);
526 assert(OldOffsetSize == NewOffsetSize);
536 for (
const auto &E : IndexEntries)
537 for (
size_t I = 0;
I != std::size(E.second.Contributions); ++
I)
538 if (ContributionOffsets[
I])
540 ? E.second.Contributions[
I].getOffset32()
541 : E.second.Contributions[
I].getLength32()),
549 if (IndexEntries.
empty())
552 unsigned Columns = 0;
553 for (
auto &
C : ContributionOffsets)
560 for (
const auto &
P : IndexEntries) {
563 auto HP = ((S >> 32) & Mask) | 1;
565 assert(S != IndexEntries.
begin()[Buckets[
H] - 1].first &&
580 for (
const auto &
I : Buckets)
584 for (
const auto &
I : Buckets)
588 for (
size_t I = 0;
I != ContributionOffsets.
size(); ++
I)
589 if (ContributionOffsets[
I])
602 std::string(
"duplicate DWO ID (") +
utohexstr(PrevE.first) +
") in " +
604 PrevE.second.DWOName) +
609 const StringMap<std::pair<MCSection *, DWARFSectionKind>> &KnownSections,
617 std::vector<StringRef> &CurTypesSection,
618 std::vector<StringRef> &CurInfoSection,
StringRef &AbbrevSection,
624 if (Section.isVirtual())
641 Name = Name.substr(Name.find_first_not_of(
"._"));
643 auto SectionPair = KnownSections.find(Name);
644 if (SectionPair == KnownSections.end())
649 SectionLength.push_back(std::make_pair(
Kind, Contents.
size()));
652 if (
Kind == DW_SECT_ABBREV) {
653 AbbrevSection = Contents;
657 MCSection *OutSection = SectionPair->second.first;
658 if (OutSection == StrOffsetSection)
659 CurStrOffsetSection = Contents;
660 else if (OutSection == StrSection)
661 CurStrSection = Contents;
662 else if (OutSection == TypesSection)
663 CurTypesSection.push_back(Contents);
664 else if (OutSection == CUIndexSection)
665 CurCUIndexSection = Contents;
666 else if (OutSection == TUIndexSection)
667 CurTUIndexSection = Contents;
668 else if (OutSection == InfoSection)
669 CurInfoSection.push_back(Contents);
681 MCSection *
const StrSection = MCOFI.getDwarfStrDWOSection();
682 MCSection *
const StrOffsetSection = MCOFI.getDwarfStrOffDWOSection();
683 MCSection *
const TypesSection = MCOFI.getDwarfTypesDWOSection();
684 MCSection *
const CUIndexSection = MCOFI.getDwarfCUIndexSection();
685 MCSection *
const TUIndexSection = MCOFI.getDwarfTUIndexSection();
686 MCSection *
const InfoSection = MCOFI.getDwarfInfoDWOSection();
688 {
"debug_info.dwo", {InfoSection, DW_SECT_INFO}},
690 {
"debug_str_offsets.dwo", {StrOffsetSection, DW_SECT_STR_OFFSETS}},
693 {
"debug_line.dwo", {MCOFI.getDwarfLineDWOSection(), DW_SECT_LINE}},
694 {
"debug_macro.dwo", {MCOFI.getDwarfMacroDWOSection(), DW_SECT_MACRO}},
695 {
"debug_abbrev.dwo", {MCOFI.getDwarfAbbrevDWOSection(), DW_SECT_ABBREV}},
696 {
"debug_loclists.dwo",
697 {MCOFI.getDwarfLoclistsDWOSection(), DW_SECT_LOCLISTS}},
698 {
"debug_rnglists.dwo",
699 {MCOFI.getDwarfRnglistsDWOSection(), DW_SECT_RNGLISTS}},
706 uint32_t ContributionOffsets[8] = {};
710 bool AnySectionOverflow =
false;
717 std::deque<SmallString<32>> UncompressedSections;
719 for (
const auto &
Input : Inputs) {
723 [&](std::unique_ptr<ECError> EC) ->
Error {
724 return createFileError(Input, Error(std::move(EC)));
728 auto &Obj = *ErrOrObj->getBinary();
735 std::vector<StringRef> CurTypesSection;
736 std::vector<StringRef> CurInfoSection;
746 for (
const auto &Section : Obj.sections())
748 KnownSections, StrSection, StrOffsetSection, TypesSection,
749 CUIndexSection, TUIndexSection, InfoSection, Section, Out,
750 UncompressedSections, ContributionOffsets, CurEntry,
751 CurStrSection, CurStrOffsetSection, CurTypesSection,
752 CurInfoSection, AbbrevSection, CurCUIndexSection,
753 CurTUIndexSection, SectionLength))
756 if (CurInfoSection.empty())
767 IndexVersion =
Version < 5 ? 2 : 5;
769 }
else if (
Version != Header.Version) {
771 "incompatible DWARF compile unit version: " +
Input +
" (version " +
772 utostr(Header.Version) +
") and " + FirstInput.
str() +
" (version " +
777 CurStrOffsetSection, Header.Version, SectionLength,
780 for (
auto Pair : SectionLength) {
784 uint32_t OldOffset = ContributionOffsets[Index];
786 if (OldOffset > ContributionOffsets[Index]) {
788 for (
auto &Section : Obj.sections()) {
789 if (SectionIndex == Index) {
791 OldOffset, ContributionOffsets[Index], *Section.getName(),
792 OverflowOptValue, AnySectionOverflow))
797 if (AnySectionOverflow)
804 if (CurCUIndexSection.
empty()) {
805 bool FoundCUUnit =
false;
809 while (Info.size() > UnitOffset) {
819 C.setOffset(InfoSectionOffset);
820 C.setLength(Header.Length + 4);
822 if (std::numeric_limits<uint32_t>::max() - InfoSectionOffset <
825 InfoSectionOffset, InfoSectionOffset +
C.getLength32(),
826 "debug_info", OverflowOptValue, AnySectionOverflow))
828 if (AnySectionOverflow) {
829 if (Header.Version < 5 ||
830 Header.UnitType == dwarf::DW_UT_split_compile)
836 UnitOffset +=
C.getLength32();
837 if (Header.Version < 5 ||
838 Header.UnitType == dwarf::DW_UT_split_compile) {
840 Header, AbbrevSection,
841 Info.
substr(UnitOffset -
C.getLength32(),
C.getLength32()),
842 CurStrOffsetSection, CurStrSection);
846 const auto &
ID = *EID;
847 auto P = IndexEntries.
insert(std::make_pair(
ID.Signature, Entry));
850 P.first->second.Name =
ID.Name;
851 P.first->second.DWOName =
ID.DWOName;
854 }
else if (Header.UnitType == dwarf::DW_UT_split_type) {
855 auto P = TypeIndexEntries.
insert(
856 std::make_pair(*Header.Signature, Entry));
861 Info.substr(UnitOffset -
C.getLength32(),
C.getLength32()));
862 InfoSectionOffset +=
C.getLength32();
864 if (AnySectionOverflow)
871 if (IndexVersion == 2) {
874 Out, TypeIndexEntries, TypesSection, CurTypesSection, CurEntry,
876 OverflowOptValue, AnySectionOverflow))
879 if (AnySectionOverflow)
884 if (CurInfoSection.size() != 1)
886 "info section in a .dwp file");
887 StringRef DwpSingleInfoSection = CurInfoSection.front();
890 DataExtractor CUIndexData(CurCUIndexSection, Obj.isLittleEndian(), 0);
891 if (!CUIndex.
parse(CUIndexData))
896 " and expecting " +
utostr(IndexVersion));
900 auto *
I = E.getContributions();
903 auto P = IndexEntries.
insert(std::make_pair(E.getSignature(), CurEntry));
919 const auto &
ID = *EID;
922 auto &NewEntry =
P.first->second;
923 NewEntry.Name =
ID.Name;
924 NewEntry.DWOName =
ID.DWOName;
925 NewEntry.DWPName =
Input;
931 C.setOffset(
C.getOffset() +
I->getOffset());
932 C.setLength(
I->getLength());
936 auto &
C = NewEntry.Contributions[Index];
938 C.setOffset(InfoSectionOffset);
939 InfoSectionOffset +=
C.getLength32();
942 if (!CurTUIndexSection.
empty()) {
948 TUSectionKind = DW_SECT_INFO;
949 OutSection = InfoSection;
950 TypeInputSection = DwpSingleInfoSection;
953 if (CurTypesSection.size() != 1)
955 "multiple type unit sections in .dwp file");
958 OutSection = TypesSection;
959 TypeInputSection = CurTypesSection.front();
963 DataExtractor TUIndexData(CurTUIndexSection, Obj.isLittleEndian(), 0);
964 if (!TUIndex.
parse(TUIndexData))
969 " and expecting " +
utostr(IndexVersion));
971 unsigned TypesContributionIndex =
974 Out, TypeIndexEntries, TUIndex, OutSection, TypeInputSection,
975 CurEntry, ContributionOffsets[TypesContributionIndex],
976 TypesContributionIndex, OverflowOptValue, AnySectionOverflow))
979 if (AnySectionOverflow)
987 ContributionOffsets[0] = 0;
989 writeIndex(Out, MCOFI.getDwarfTUIndexSection(), ContributionOffsets,
990 TypeIndexEntries, IndexVersion);
997 ContributionOffsets[0] = 1;
1000 writeIndex(Out, MCOFI.getDwarfCUIndexSection(), ContributionOffsets,
1001 IndexEntries, IndexVersion);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Analysis containing CSE Info
static unsigned getContributionIndex(DWARFSectionKind Kind, uint32_t IndexVersion)
static uint64_t getCUAbbrev(StringRef Abbrev, uint64_t AbbrCode)
static Error handleCompressedSection(std::deque< SmallString< 32 > > &UncompressedSections, SectionRef Sec, StringRef Name, StringRef &Contents)
static std::string buildDWODescription(StringRef Name, StringRef DWPName, StringRef DWOName)
static uint64_t debugStrOffsetsHeaderSize(DataExtractor StrOffsetsData, uint16_t DwarfVersion)
static Expected< const char * > getIndexedString(dwarf::Form Form, DataExtractor InfoData, uint64_t &InfoOffset, StringRef StrOffsets, StringRef Str, uint16_t Version)
static Error addAllTypesFromTypesSection(MCStreamer &Out, MapVector< uint64_t, UnitIndexEntry > &TypeIndexEntries, MCSection *OutputTypes, const std::vector< StringRef > &TypesSections, const UnitIndexEntry &CUEntry, uint32_t &TypesOffset, OnCuIndexOverflow OverflowOptValue, bool &AnySectionOverflow)
static unsigned getOnDiskSectionId(unsigned Index)
static Expected< CompileUnitIdentifiers > getCUIdentifiers(InfoSectionUnitHeader &Header, StringRef Abbrev, StringRef Info, StringRef StrOffsets, StringRef Str)
static Error sectionOverflowErrorOrWarning(uint32_t PrevOffset, uint32_t OverflowedOffset, StringRef SectionName, OnCuIndexOverflow OverflowOptValue, bool &AnySectionOverflow)
static mc::RegisterMCTargetOptionsFlags MCTargetOptionsFlags
static StringRef getSubsection(StringRef Section, const DWARFUnitIndex::Entry &Entry, DWARFSectionKind Kind)
static bool isSupportedSectionKind(DWARFSectionKind Kind)
static Error addAllTypesFromDWP(MCStreamer &Out, MapVector< uint64_t, UnitIndexEntry > &TypeIndexEntries, const DWARFUnitIndex &TUIndex, MCSection *OutputTypes, StringRef Types, const UnitIndexEntry &TUEntry, uint32_t &TypesOffset, unsigned TypesContributionIndex, OnCuIndexOverflow OverflowOptValue, bool &AnySectionOverflow)
OptimizedStructLayoutField Field
static uint32_t getFlags(const Symbol *Sym)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
void setOffset(uint64_t Value)
void setLength(uint64_t Value)
uint32_t getLength32() const
uint64_t getOffset() const
uint32_t getVersion() const
LLVM_ABI bool parse(DataExtractor IndexData)
ArrayRef< DWARFSectionKind > getColumnKinds() const
ArrayRef< Entry > getRows() const
uint64_t getOffset(const char *Str, unsigned Length)
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
const MCObjectFileInfo * getObjectFileInfo() const
Instances of this class represent a uniqued identifier for a section in the current translation unit.
Streaming machine code generation interface.
MCContext & getContext() const
virtual void emitIntValue(uint64_t Value, unsigned Size)
Special case of EmitValue that avoids the client having to pass in a MCExpr for constant integers.
virtual void switchSection(MCSection *Section, uint32_t Subsec=0)
Set the current section where code is being emitted to Section.
virtual void emitBytes(StringRef Data)
Emit the bytes in Data into the output.
This class implements a map that also provides access to all stored values in a deterministic order.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
void reserve(size_type N)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
StringRef - Represent a constant reference to a string, i.e.
std::string str() const
str - Get the contents as an std::string.
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
constexpr bool empty() const
empty - Check if the string is empty.
char back() const
back - Get the last character in the string.
constexpr size_t size() const
size - Get the string size.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
static LLVM_ABI void defaultWarningHandler(Error Warning)
Implement default handling for Warning.
static LLVM_ABI Expected< Decompressor > create(StringRef Name, StringRef Data, bool IsLE, bool Is64Bit)
Create decompressor object.
static Expected< OwningBinary< ObjectFile > > createObjectFile(StringRef ObjectPath)
This is a value type class that represents a single section in the list of sections in the object fil...
const ObjectFile * getObject() const
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
@ DW_LENGTH_DWARF64
Indicator of 64-bit DWARF format.
Error createError(const Twine &Err)
This is an optimization pass for GlobalISel generic memory operations.
Error createFileError(const Twine &F, Error E)
Concatenate a source file path and/or name with an Error.
LLVM_ABI Error buildDuplicateError(const std::pair< uint64_t, UnitIndexEntry > &PrevE, const CompileUnitIdentifiers &ID, StringRef DWPName)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI void writeIndex(MCStreamer &Out, MCSection *Section, ArrayRef< unsigned > ContributionOffsets, const MapVector< uint64_t, UnitIndexEntry > &IndexEntries, uint32_t IndexVersion)
Error handleErrors(Error E, HandlerTs &&... Hs)
Pass the ErrorInfo(s) contained in E to their respective handlers.
std::string utohexstr(uint64_t X, bool LowerCase=false, unsigned Width=0)
LLVM_ABI void writeStringsAndOffsets(MCStreamer &Out, DWPStringPool &Strings, MCSection *StrOffsetSection, StringRef CurStrSection, StringRef CurStrOffsetSection, uint16_t Version)
std::string utostr(uint64_t X, bool isNeg=false)
std::vector< std::pair< DWARFSectionKind, uint32_t > > SectionLengths
DWARFSectionKind
The enum of section identifiers to be used in internal interfaces.
@ DW_SECT_EXT_unknown
Denotes a value read from an index section that does not correspond to any of the supported standards...
LLVM_ABI uint32_t serializeSectionKind(DWARFSectionKind Kind, unsigned IndexVersion)
Convert the internal value for a section kind to an on-disk value.
FunctionAddr VTableAddr uintptr_t uintptr_t Version
static void writeNewOffsetsTo(MCStreamer &Out, DataExtractor &Data, DenseMap< uint64_t, uint64_t > &OffsetRemapping, uint64_t &Offset, const uint64_t Size, uint32_t OldOffsetSize, uint32_t NewOffsetSize)
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ABI Error handleSection(const StringMap< std::pair< MCSection *, DWARFSectionKind > > &KnownSections, const MCSection *StrSection, const MCSection *StrOffsetSection, const MCSection *TypesSection, const MCSection *CUIndexSection, const MCSection *TUIndexSection, const MCSection *InfoSection, const object::SectionRef &Section, MCStreamer &Out, std::deque< SmallString< 32 > > &UncompressedSections, uint32_t(&ContributionOffsets)[8], UnitIndexEntry &CurEntry, StringRef &CurStrSection, StringRef &CurStrOffsetSection, std::vector< StringRef > &CurTypesSection, std::vector< StringRef > &CurInfoSection, StringRef &AbbrevSection, StringRef &CurCUIndexSection, StringRef &CurTUIndexSection, SectionLengths &SectionLength)
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
FunctionAddr VTableAddr uintptr_t uintptr_t Data
void writeIndexTable(MCStreamer &Out, ArrayRef< unsigned > ContributionOffsets, const MapVector< uint64_t, UnitIndexEntry > &IndexEntries, const AccessField &Field)
std::string toString(const APInt &I, unsigned Radix, bool Signed, bool formatAsCLiteral=false, bool UpperCase=true, bool InsertSeparators=false)
LLVM_ABI Error write(MCStreamer &Out, ArrayRef< std::string > Inputs, OnCuIndexOverflow OverflowOptValue, Dwarf64StrOffsetsPromotion StrOffsetsOptValue)
LLVM_ABI Expected< InfoSectionUnitHeader > parseInfoSectionUnitHeader(StringRef Info)
Dwarf64StrOffsetsPromotion
@ Always
Always emit .debug_str_offsets talbes as DWARF64 for testing.
@ Disabled
Don't do any conversion of .debug_str_offsets tables.
constexpr uint64_t NextPowerOf2(uint64_t A)
Returns the next power of two (in 64-bits) that is strictly greater than A.
DWARFUnitIndex::Entry::SectionContribution Contributions[8]
Create this object with static storage to register mc-related command line options.