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

[Clang][CodeGen] __bdos off by 4 #111009

Open
Cydox opened this issue Oct 3, 2024 · 4 comments · May be fixed by #111015
Open

[Clang][CodeGen] __bdos off by 4 #111009

Cydox opened this issue Oct 3, 2024 · 4 comments · May be fixed by #111015

Comments

@Cydox
Copy link
Contributor

Cydox commented Oct 3, 2024

Under certain circumstances __bdos can be off by 4 bytes compared to gcc.

Seen in the linux kernel:
https://lore.kernel.org/linux-kernel/[email protected]/

Reproducer from Thorsten Blum (also here: https://godbolt.org/z/vvK9PE1Yq):

#include <stdio.h>
#include <stdlib.h>

typedef struct {
    int counter;
} atomic_t;

typedef struct refcount_struct {
    atomic_t refs;
} refcount_t;

struct callback_head {
    struct callback_head *next;
    void (*func)(struct callback_head *head);
} __attribute__((aligned(sizeof(void *))));
#define rcu_head callback_head

typedef struct {
    uid_t val;
} kuid_t;

typedef struct {
    gid_t val;
} kgid_t;

struct posix_acl_entry {
    short e_tag;
    unsigned short e_perm;
    union {
        kuid_t e_uid;
        kgid_t e_gid;
    };
};

struct posix_acl {
    refcount_t a_refcount;
    struct rcu_head a_rcu;
    unsigned int a_count;
    struct posix_acl_entry a_entries[] __attribute__((counted_by(a_count)));
};

int main() {
    unsigned int count = 1;
    struct posix_acl *acl;

    acl = malloc(sizeof(struct posix_acl) +
                 sizeof(struct posix_acl_entry) * count);
    acl->a_count = count;

    printf("%zu", __builtin_dynamic_object_size(acl, 0));
    return 0;
}
@github-actions github-actions bot added the clang Clang issues not falling into any other category label Oct 3, 2024
@Cydox
Copy link
Contributor Author

Cydox commented Oct 3, 2024

I do have a fix for this I'll submit shortly.

@EugeneZelenko EugeneZelenko added clang:codegen and removed clang Clang issues not falling into any other category labels Oct 3, 2024
@llvmbot
Copy link
Collaborator

llvmbot commented Oct 3, 2024

@llvm/issue-subscribers-clang-codegen

Author: Jan Hendrik Farr (Cydox)

Under certain circumstances __bdos can be off by 4 bytes compared to gcc.

Seen in the linux kernel:
https://lore.kernel.org/linux-kernel/3D0816D1-0807-4D37-8D5F-3C55CA910FAA@linux.dev/

Reproducer from Thorsten Blum (also here: https://godbolt.org/z/vvK9PE1Yq):

#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;

typedef struct {
    int counter;
} atomic_t;

typedef struct refcount_struct {
    atomic_t refs;
} refcount_t;

struct callback_head {
    struct callback_head *next;
    void (*func)(struct callback_head *head);
} __attribute__((aligned(sizeof(void *))));
#define rcu_head callback_head

typedef struct {
    uid_t val;
} kuid_t;

typedef struct {
    gid_t val;
} kgid_t;

struct posix_acl_entry {
    short e_tag;
    unsigned short e_perm;
    union {
        kuid_t e_uid;
        kgid_t e_gid;
    };
};

struct posix_acl {
    refcount_t a_refcount;
    struct rcu_head a_rcu;
    unsigned int a_count;
    struct posix_acl_entry a_entries[] __attribute__((counted_by(a_count)));
};

int main() {
    unsigned int count = 1;
    struct posix_acl *acl;

    acl = malloc(sizeof(struct posix_acl) +
                 sizeof(struct posix_acl_entry) * count);
    acl-&gt;a_count = count;

    printf("%zu", __builtin_dynamic_object_size(acl, 0));
    return 0;
}

@nickdesaulniers
Copy link
Member

cc @nathanchance @kees @bwendling

@Cydox
Copy link
Contributor Author

Cydox commented Oct 3, 2024

Fix is at: https://github.com/Cydox/llvm-project/tree/fix-bdos-offby4
Just adding an additional test based on the reproducer now (and waiting for a full recompile as I just rebased on top of main)

Cydox added a commit to Cydox/llvm-project that referenced this issue Oct 3, 2024
Fixes: llvm#111009

Change the behavior of __bdos to be in-line with gcc by changing the
behvaior from:

max(sizeof(struct s), offsetof(struct s, array) + p->count * sizeof(*p->array))

to:

sizeof(struct s) + p->count * sizeof(*p->array))
@Cydox Cydox linked a pull request Oct 3, 2024 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants