From 83e0e425c61c4e03f61114a88f117db1553cd44c Mon Sep 17 00:00:00 2001 From: Fengwei Yin Date: Sat, 24 May 2014 05:32:09 +0800 Subject: [PATCH] x86_64: Align uint64_t/int64_t structure member to 8 bytes To make sure the stature which pass between 32/64bit process have same memory layout for 32/64bit. Signed-off-by: Fengwei Yin Co-Authored-by: Narayan Kamath (Unit test only.) Change-Id: I1bc2d12cce41ec0bc484adcaf968f274bec75c12 --- include/input/Input.h | 2 +- include/input/InputTransport.h | 22 ++++++--- libs/input/tests/Android.mk | 11 +++++ libs/input/tests/StructLayout_test.cpp | 67 ++++++++++++++++++++++++++ 4 files changed, 94 insertions(+), 8 deletions(-) create mode 100644 libs/input/tests/StructLayout_test.cpp diff --git a/include/input/Input.h b/include/input/Input.h index e77807634..7c662a7aa 100644 --- a/include/input/Input.h +++ b/include/input/Input.h @@ -170,7 +170,7 @@ struct PointerCoords { enum { MAX_AXES = 14 }; // 14 so that sizeof(PointerCoords) == 64 // Bitfield of axes that are present in this structure. - uint64_t bits; + uint64_t bits __attribute__((aligned(8))); // Values of axes that are stored in this structure packed in order by axis id // for each axis that is present in the structure according to 'bits'. diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h index 8ffdfca0d..e7e383b48 100644 --- a/include/input/InputTransport.h +++ b/include/input/InputTransport.h @@ -39,6 +39,9 @@ namespace android { /* * Intermediate representation used to send input events and related signals. + * + * Note that this structure is used for IPCs so its layout must be identical + * on 64 and 32 bit processes. This is tested in StructLayout_test.cpp. */ struct InputMessage { enum { @@ -49,13 +52,17 @@ struct InputMessage { struct Header { uint32_t type; - uint32_t padding; // 8 byte alignment for the body that follows + // We don't need this field in order to align the body below but we + // leave it here because InputMessage::size() and other functions + // compute the size of this structure as sizeof(Header) + sizeof(Body). + uint32_t padding; } header; + // Body *must* be 8 byte aligned. union Body { struct Key { uint32_t seq; - nsecs_t eventTime; + nsecs_t eventTime __attribute__((aligned(8))); int32_t deviceId; int32_t source; int32_t action; @@ -64,7 +71,7 @@ struct InputMessage { int32_t scanCode; int32_t metaState; int32_t repeatCount; - nsecs_t downTime; + nsecs_t downTime __attribute__((aligned(8))); inline size_t size() const { return sizeof(Key); @@ -73,7 +80,7 @@ struct InputMessage { struct Motion { uint32_t seq; - nsecs_t eventTime; + nsecs_t eventTime __attribute__((aligned(8))); int32_t deviceId; int32_t source; int32_t action; @@ -81,13 +88,14 @@ struct InputMessage { int32_t metaState; int32_t buttonState; int32_t edgeFlags; - nsecs_t downTime; + nsecs_t downTime __attribute__((aligned(8))); float xOffset; float yOffset; float xPrecision; float yPrecision; uint32_t pointerCount; - struct Pointer { + // Note that PointerCoords requires 8 byte alignment. + struct Pointer{ PointerProperties properties; PointerCoords coords; } pointers[MAX_POINTERS]; @@ -112,7 +120,7 @@ struct InputMessage { return sizeof(Finished); } } finished; - } body; + } __attribute__((aligned(8))) body; bool isValid(size_t actualSize) const; size_t size() const; diff --git a/libs/input/tests/Android.mk b/libs/input/tests/Android.mk index c62dff13f..9612a65fe 100644 --- a/libs/input/tests/Android.mk +++ b/libs/input/tests/Android.mk @@ -29,5 +29,16 @@ $(foreach file,$(test_src_files), \ $(eval include $(BUILD_NATIVE_TEST)) \ ) +# NOTE: This is a compile time test, and does not need to be +# run. All assertions are static_asserts and will fail during +# buildtime if something's wrong. +include $(CLEAR_VARS) +LOCAL_SRC_FILES := StructLayout_test.cpp +LOCAL_MODULE := StructLayout_test +LOCAL_CFLAGS := -std=c++11 -O0 +LOCAL_MULTILIB := both +include $(BUILD_STATIC_LIBRARY) + + # Build the manual test programs. include $(call all-makefiles-under, $(LOCAL_PATH)) diff --git a/libs/input/tests/StructLayout_test.cpp b/libs/input/tests/StructLayout_test.cpp new file mode 100644 index 000000000..83bc6ae0b --- /dev/null +++ b/libs/input/tests/StructLayout_test.cpp @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +namespace android { + +#define CHECK_OFFSET(type, member, expected_offset) \ + static_assert((offsetof(type, member) == expected_offset), "") + +struct Foo { + uint32_t dummy; + PointerCoords coords; +}; + +void TestPointerCoordsAlignment() { + CHECK_OFFSET(Foo, coords, 8); +} + +void TestInputMessageAlignment() { + CHECK_OFFSET(InputMessage, body, 8); + + CHECK_OFFSET(InputMessage::Body::Key, seq, 0); + CHECK_OFFSET(InputMessage::Body::Key, eventTime, 8); + CHECK_OFFSET(InputMessage::Body::Key, deviceId, 16); + CHECK_OFFSET(InputMessage::Body::Key, source, 20); + CHECK_OFFSET(InputMessage::Body::Key, action, 24); + CHECK_OFFSET(InputMessage::Body::Key, flags, 28); + CHECK_OFFSET(InputMessage::Body::Key, keyCode, 32); + CHECK_OFFSET(InputMessage::Body::Key, scanCode, 36); + CHECK_OFFSET(InputMessage::Body::Key, metaState, 40); + CHECK_OFFSET(InputMessage::Body::Key, repeatCount, 44); + CHECK_OFFSET(InputMessage::Body::Key, downTime, 48); + + CHECK_OFFSET(InputMessage::Body::Motion, seq, 0); + CHECK_OFFSET(InputMessage::Body::Motion, eventTime, 8); + CHECK_OFFSET(InputMessage::Body::Motion, deviceId, 16); + CHECK_OFFSET(InputMessage::Body::Motion, source, 20); + CHECK_OFFSET(InputMessage::Body::Motion, action, 24); + CHECK_OFFSET(InputMessage::Body::Motion, flags, 28); + CHECK_OFFSET(InputMessage::Body::Motion, metaState, 32); + CHECK_OFFSET(InputMessage::Body::Motion, buttonState, 36); + CHECK_OFFSET(InputMessage::Body::Motion, edgeFlags, 40); + CHECK_OFFSET(InputMessage::Body::Motion, downTime, 48); + CHECK_OFFSET(InputMessage::Body::Motion, xOffset, 56); + CHECK_OFFSET(InputMessage::Body::Motion, yOffset, 60); + CHECK_OFFSET(InputMessage::Body::Motion, xPrecision, 64); + CHECK_OFFSET(InputMessage::Body::Motion, yPrecision, 68); + CHECK_OFFSET(InputMessage::Body::Motion, pointerCount, 72); + CHECK_OFFSET(InputMessage::Body::Motion, pointers, 80); +} + +} // namespace android