Re: [RFC 2/6] objtool: arm64: Add required implementation for supporting the aarch64 architecture in objtool.

Raphael Gault
2019-04-24T16:16:45Z

On 4/23/19 9:18 PM, Josh Poimboeuf wrote:
> On Tue, Apr 09, 2019 at 02:52:39PM +0100, Raphael Gault wrote:
>> Provide implementation for the arch-dependent functions that are called by the main check
>> function of objtool.
>> The ORC unwinder is not yet supported by the arm64 architecture so we only provide a dummy
>> interface for now.
>> The decoding of the instruction is split into classes and subclasses as described into
>> the Instruction Encoding in the ArmV8.5 Architecture Reference Manual.
>
> Where did the code for the decoder come from? Was it written from
> scratch?
>

This decoder was indeed written from scratch based on the armv8 ARM. The
automatic generation idea hasn't really been discussed yet.

>> diff --git a/tools/objtool/arch/arm64/include/arch_special.h b/tools/objtool/arch/arm64/include/arch_special.h
>> new file mode 100644
>> index 000000000000..54bcce4c58c0
>> --- /dev/null
>> +++ b/tools/objtool/arch/arm64/include/arch_special.h
>> @@ -0,0 +1,44 @@
>> +/*
>> + * This program is free software; you can redistribute it and/or
>> + * modify it under the terms of the GNU General Public License
>> + * as published by the Free Software Foundation; either version 2
>> + * of the License, or (at your option) any later version.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>> + * GNU General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program; if not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>
> Needs a header guard.
>
>> +#define EX_ENTRY_SIZE8
>> +#define EX_ORIG_OFFSET0
>> +#define EX_NEW_OFFSET4
>> +
>> +#define JUMP_ENTRY_SIZE16
>> +#define JUMP_ORIG_OFFSET0
>> +#define JUMP_NEW_OFFSET4
>> +
>> +#define ALT_ENTRY_SIZE12
>> +#define ALT_ORIG_OFFSET0
>> +#define ALT_NEW_OFFSET4
>> +#define ALT_FEATURE_OFFSET8
>> +#define ALT_ORIG_LEN_OFFSET10
>> +#define ALT_NEW_LEN_OFFSET11
>> +
>> +/*
>> + * On arm64 the .altinstr_replacement is not always marked
>> + * as containing executable instruction. But we still want
>> + * to process it so we ignore the SHF_EXEC flag
>> + */
>> +#define IGNORE_SHF_EXEC_FLAG1
>> +
>> +/*
>> + * The jump table detection is not the same on arm64 so for
>> + * now we just detect if it is a dynamic jump (br <Xn> insn)
>> + */
>> +#define JUMP_DYNAMIC_IS_SWITCH_TABLE1
>
> Same as for x86, these flags should be added in the same patch which
> uses them.
>

This will disappear in the next version, thanks.

>> +
>> +#define X86_FEATURE_POPCNT (4*32+23)
>> diff --git a/tools/objtool/arch/arm64/include/asm/orc_types.h b/tools/objtool/arch/arm64/include/asm/orc_types.h
>> new file mode 100644
>> index 000000000000..46f516dd80ce
>> --- /dev/null
>> +++ b/tools/objtool/arch/arm64/include/asm/orc_types.h
>> @@ -0,0 +1,109 @@
>> +/*
>> + * Copyright (C) 2017 Josh Poimboeuf <jpoimboe@redhat.com>
>> + *
>> + * This program is free software; you can redistribute it and/or
>> + * modify it under the terms of the GNU General Public License
>> + * as published by the Free Software Foundation; either version 2
>> + * of the License, or (at your option) any later version.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>> + * GNU General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program; if not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#ifndef _ORC_TYPES_H
>> +#define _ORC_TYPES_H
>> +
>> +#include <linux/types.h>
>> +#include <linux/compiler.h>
>> +
>> +/*
>> + * The ORC_REG_* registers are base registers which are used to find other
>> + * registers on the stack.
>> + *
>> + * ORC_REG_PREV_SP, also known as DWARF Call Frame Address (CFA), is the
>> + * address of the previous frame: the caller's SP before it called the current
>> + * function.
>> + *
>> + * ORC_REG_UNDEFINED means the corresponding register's value didn't change in
>> + * the current frame.
>> + *
>> + * The most commonly used base registers are SP and BP -- which the previous SP
>> + * is usually based on -- and PREV_SP and UNDEFINED -- which the previous BP is
>> + * usually based on.
>> + *
>> + * The rest of the base registers are needed for special cases like entry code
>> + * and GCC realigned stacks.
>> + */
>> +#define ORC_REG_UNDEFINED0
>> +#define ORC_REG_PREV_SP1
>> +#define ORC_REG_DX2
>> +#define ORC_REG_DI3
>> +#define ORC_REG_BP4
>> +#define ORC_REG_SP5
>> +#define ORC_REG_R106
>> +#define ORC_REG_R137
>> +#define ORC_REG_BP_INDIRECT8
>> +#define ORC_REG_SP_INDIRECT9
>> +#define ORC_REG_MAX15
>> +
>> +/*
>> + * ORC_TYPE_CALL: Indicates that sp_reg+sp_offset resolves to PREV_SP (the
>> + * caller's SP right before it made the call). Used for all callable
>> + * functions, i.e. all C code and all callable asm functions.
>> + *
>> + * ORC_TYPE_REGS: Used in entry code to indicate that sp_reg+sp_offset points
>> + * to a fully populated pt_regs from a syscall, interrupt, or exception.
>> + *
>> + * ORC_TYPE_REGS_IRET: Used in entry code to indicate that sp_reg+sp_offset
>> + * points to the iret return frame.
>> + *
>> + * The UNWIND_HINT macros are used only for the unwind_hint struct. They
>> + * aren't used in struct orc_entry due to size and complexity constraints.
>> + * Objtool converts them to real types when it converts the hints to orc
>> + * entries.
>> + */
>> +#define ORC_TYPE_CALL0
>> +#define ORC_TYPE_REGS1
>> +#define ORC_TYPE_REGS_IRET2
>> +#define UNWIND_HINT_TYPE_SAVE3
>> +#define UNWIND_HINT_TYPE_RESTORE4
>> +
>> +#ifndef __ASSEMBLY__
>> +/*
>> + * This struct is more or less a vastly simplified version of the DWARF Call
>> + * Frame Information standard. It contains only the necessary parts of DWARF
>> + * CFI, simplified for ease of access by the in-kernel unwinder. It tells the
>> + * unwinder how to find the previous SP and BP (and sometimes entry regs) on
>> + * the stack for a given code address. Each instance of the struct corresponds
>> + * to one or more code locations.
>> + */
>> +struct orc_entry {
>> +s16sp_offset;
>> +s16bp_offset;
>> +unsignedsp_reg:4;
>> +unsignedbp_reg:4;
>> +unsignedtype:2;
>> +unsignedend:1;
>> +} __packed;
>> +
>> +/*
>> + * This struct is used by asm and inline asm code to manually annotate the
>> + * location of registers on the stack for the ORC unwinder.
>> + *
>> + * Type can be either ORC_TYPE_* or UNWIND_HINT_TYPE_*.
>> + */
>> +struct unwind_hint {
>> +u32ip;
>> +s16sp_offset;
>> +u8sp_reg;
>> +u8type;
>> +u8end;
>> +};
>> +#endif /* __ASSEMBLY__ */
>> +
>> +#endif /* _ORC_TYPES_H */
>
> It seems odd to have the above header file in arm64 code, since it
> doesn't implement ORC. Is it really needed?
>

The unwind_hint part can safely be removed. However the orc_entry seems
to be needed since the struct instruction comports a struct orc_entry
field. I have chosen to let it here as well but maybe a better approach
is possible.

Cheers,

--
Raphael Gault
IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.