Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

adjust tracepoint field type based on size #1808

Merged
merged 1 commit into from
Jun 11, 2018
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
adjust tracepoint field type based on size
Fix issue #1807

tracepoint may have a format like this:
(from syscalls/sys_enter_socket)
	field:unsigned short common_type;	offset:0;	size:2;	signed:0;
	field:unsigned char common_flags;	offset:2;	size:1;	signed:0;
	field:unsigned char common_preempt_count;	offset:3;	size:1;	signed:0;
	field:int common_pid;	offset:4;	size:4;	signed:1;

	field:int __syscall_nr;	offset:8;	size:4;	signed:1;
	field:int family;	offset:16;	size:8;	signed:0;
	field:int type;	offset:24;	size:8;	signed:0;
	field:int protocol;	offset:32;	size:8;	signed:0;

Current rewriter generates:
    struct tracepoint__syscalls__sys_enter_socket {
	    u64 __do_not_use__;
	    int __syscall_nr;
	    int family;
	    int type;
	    int protocol;
    };

This is incorrect as in the above structure, offsets of
`family`/`type`/`procotol` becomingg 12/16/20.

This patch fixed the issue by adjusting field type based on its size.
The new structure:
    struct tracepoint__syscalls__sys_enter_socket {
	    u64 __do_not_use__;
	    int __syscall_nr;
	    s64 family;
	    s64 type;
	    s64 protocol;
    };
The offsets of all fields are correct now.

Signed-off-by: Yonghong Song <[email protected]>
  • Loading branch information
yonghong-song committed Jun 10, 2018
commit 7c489469a7dc722334be65e48f5584fe6dcfb306
46 changes: 44 additions & 2 deletions src/cc/frontends/clang/tp_frontend_action.cc
Original file line number Diff line number Diff line change
Expand Up @@ -62,16 +62,32 @@ static inline field_kind_t _get_field_kind(string const& line,
if (field_pos == string::npos)
return field_kind_t::invalid;

auto semi_pos = line.find(';', field_pos);
auto field_semi_pos = line.find(';', field_pos);
if (field_semi_pos == string::npos)
return field_kind_t::invalid;

auto offset_pos = line.find("offset:", field_semi_pos);
if (offset_pos == string::npos)
return field_kind_t::invalid;

auto semi_pos = line.find(';', offset_pos);
if (semi_pos == string::npos)
return field_kind_t::invalid;

auto size_pos = line.find("size:", semi_pos);
if (size_pos == string::npos)
return field_kind_t::invalid;

semi_pos = line.find(';', size_pos);
if (semi_pos == string::npos)
return field_kind_t::invalid;

auto size_str = line.substr(size_pos + 5,
semi_pos - size_pos - 5);
int size = std::stoi(size_str, nullptr);

auto field = line.substr(field_pos + 6/*"field:"*/,
semi_pos - field_pos - 6);
field_semi_pos - field_pos - 6);
auto pos = field.find_last_of("\t ");
if (pos == string::npos)
return field_kind_t::invalid;
Expand All @@ -83,6 +99,32 @@ static inline field_kind_t _get_field_kind(string const& line,
if (field_name.find("common_") == 0)
return field_kind_t::common;

// adjust the field_type based on the size of field
// otherwise, incorrect value may be retrieved for big endian
// and the field may have incorrect structure offset.
if (size == 2) {
if (field_type == "char" || field_type == "int8_t")
field_type = "s16";
if (field_type == "unsigned char" || field_type == "uint8_t")
field_type = "u16";
} else if (size == 4) {
if (field_type == "char" || field_type == "short" ||
field_type == "int8_t" || field_type == "int16_t")
field_type = "s32";
if (field_type == "unsigned char" || field_type == "unsiggned short" ||
field_type == "uint8_t" || field_type == "uint16_t")
field_type = "u32";
} else if (size == 8) {
if (field_type == "char" || field_type == "short" || field_type == "int" ||
field_type == "int8_t" || field_type == "int16_t" ||
field_type == "int32_t")
field_type = "s64";
if (field_type == "unsigned char" || field_type == "unsiggned short" ||
field_type == "unsigned int" || field_type == "uint8_t" ||
field_type == "uint16_t" || field_type == "uint32_t")
field_type = "u64";
}

return field_kind_t::regular;
}

Expand Down