mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 747033 - Implement dl_iterate_phdr in the custom linker. r=froydnj
--HG-- rename : mozglue/linker/CustomElf.h => mozglue/linker/Elfxx.h
This commit is contained in:
parent
7cc9baa6ef
commit
91480beb18
@ -291,6 +291,8 @@ CustomElf::GetSymbolPtrInDeps(const char *symbol) const
|
||||
return FunctionPtr(__wrap_dlsym);
|
||||
if (strcmp(symbol + 2, "addr") == 0)
|
||||
return FunctionPtr(__wrap_dladdr);
|
||||
if (strcmp(symbol + 2, "_iterate_phdr") == 0)
|
||||
return FunctionPtr(__wrap_dl_iterate_phdr);
|
||||
} else if (symbol[0] == '_' && symbol[1] == '_') {
|
||||
/* Resolve a few C++ ABI specific functions to point to ours */
|
||||
#ifdef __ARM_EABI__
|
||||
|
@ -5,234 +5,9 @@
|
||||
#ifndef CustomElf_h
|
||||
#define CustomElf_h
|
||||
|
||||
/**
|
||||
* Android system headers have two different elf.h file. The one under linux/
|
||||
* is the most complete.
|
||||
*/
|
||||
#ifdef ANDROID
|
||||
#include <linux/elf.h>
|
||||
#else
|
||||
#include <elf.h>
|
||||
#endif
|
||||
#include <endian.h>
|
||||
#include "ElfLoader.h"
|
||||
#include "Logging.h"
|
||||
|
||||
/**
|
||||
* Generic ELF macros for the target system
|
||||
*/
|
||||
#ifdef HAVE_64BIT_OS
|
||||
#define Elf_(type) Elf64_ ## type
|
||||
#define ELFCLASS ELFCLASS64
|
||||
#define ELF_R_TYPE ELF64_R_TYPE
|
||||
#define ELF_R_SYM ELF64_R_SYM
|
||||
#ifndef ELF_ST_BIND
|
||||
#define ELF_ST_BIND ELF64_ST_BIND
|
||||
#endif
|
||||
#define PRIxAddr "lx"
|
||||
#else
|
||||
#define Elf_(type) Elf32_ ## type
|
||||
#define ELFCLASS ELFCLASS32
|
||||
#define ELF_R_TYPE ELF32_R_TYPE
|
||||
#define ELF_R_SYM ELF32_R_SYM
|
||||
#ifndef ELF_ST_BIND
|
||||
#define ELF_ST_BIND ELF32_ST_BIND
|
||||
#endif
|
||||
#define PRIxAddr "x"
|
||||
#endif
|
||||
|
||||
#ifndef __BYTE_ORDER
|
||||
#error Cannot find endianness
|
||||
#endif
|
||||
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
#define ELFDATA ELFDATA2LSB
|
||||
#elif __BYTE_ORDER == __BIG_ENDIAN
|
||||
#define ELFDATA ELFDATA2MSB
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
#define ELFOSABI ELFOSABI_LINUX
|
||||
#ifdef EI_ABIVERSION
|
||||
#define ELFABIVERSION 0
|
||||
#endif
|
||||
#else
|
||||
#error Unknown ELF OSABI
|
||||
#endif
|
||||
|
||||
#if defined(__i386__)
|
||||
#define ELFMACHINE EM_386
|
||||
|
||||
// Doing this way probably doesn't scale to other architectures
|
||||
#define R_ABS R_386_32
|
||||
#define R_GLOB_DAT R_386_GLOB_DAT
|
||||
#define R_JMP_SLOT R_386_JMP_SLOT
|
||||
#define R_RELATIVE R_386_RELATIVE
|
||||
#define RELOC(n) DT_REL ## n
|
||||
#define UNSUPPORTED_RELOC(n) DT_RELA ## n
|
||||
#define STR_RELOC(n) "DT_REL" # n
|
||||
#define Reloc Rel
|
||||
|
||||
#elif defined(__x86_64__)
|
||||
#define ELFMACHINE EM_X86_64
|
||||
|
||||
#define R_ABS R_X86_64_64
|
||||
#define R_GLOB_DAT R_X86_64_GLOB_DAT
|
||||
#define R_JMP_SLOT R_X86_64_JUMP_SLOT
|
||||
#define R_RELATIVE R_X86_64_RELATIVE
|
||||
#define RELOC(n) DT_RELA ## n
|
||||
#define UNSUPPORTED_RELOC(n) DT_REL ## n
|
||||
#define STR_RELOC(n) "DT_RELA" # n
|
||||
#define Reloc Rela
|
||||
|
||||
#elif defined(__arm__)
|
||||
#define ELFMACHINE EM_ARM
|
||||
|
||||
#ifndef R_ARM_ABS32
|
||||
#define R_ARM_ABS32 2
|
||||
#endif
|
||||
#ifndef R_ARM_GLOB_DAT
|
||||
#define R_ARM_GLOB_DAT 21
|
||||
#endif
|
||||
#ifndef R_ARM_JUMP_SLOT
|
||||
#define R_ARM_JUMP_SLOT 22
|
||||
#endif
|
||||
#ifndef R_ARM_RELATIVE
|
||||
#define R_ARM_RELATIVE 23
|
||||
#endif
|
||||
|
||||
#define R_ABS R_ARM_ABS32
|
||||
#define R_GLOB_DAT R_ARM_GLOB_DAT
|
||||
#define R_JMP_SLOT R_ARM_JUMP_SLOT
|
||||
#define R_RELATIVE R_ARM_RELATIVE
|
||||
#define RELOC(n) DT_REL ## n
|
||||
#define UNSUPPORTED_RELOC(n) DT_RELA ## n
|
||||
#define STR_RELOC(n) "DT_REL" # n
|
||||
#define Reloc Rel
|
||||
|
||||
#else
|
||||
#error Unknown ELF machine type
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Android system headers don't have all definitions
|
||||
*/
|
||||
#ifndef STN_UNDEF
|
||||
#define STN_UNDEF 0
|
||||
#endif
|
||||
#ifndef DT_INIT_ARRAY
|
||||
#define DT_INIT_ARRAY 25
|
||||
#endif
|
||||
#ifndef DT_FINI_ARRAY
|
||||
#define DT_FINI_ARRAY 26
|
||||
#endif
|
||||
#ifndef DT_INIT_ARRAYSZ
|
||||
#define DT_INIT_ARRAYSZ 27
|
||||
#endif
|
||||
#ifndef DT_FINI_ARRAYSZ
|
||||
#define DT_FINI_ARRAYSZ 28
|
||||
#endif
|
||||
#ifndef DT_RELACOUNT
|
||||
#define DT_RELACOUNT 0x6ffffff9
|
||||
#endif
|
||||
#ifndef DT_RELCOUNT
|
||||
#define DT_RELCOUNT 0x6ffffffa
|
||||
#endif
|
||||
#ifndef DT_VERSYM
|
||||
#define DT_VERSYM 0x6ffffff0
|
||||
#endif
|
||||
#ifndef DT_VERDEF
|
||||
#define DT_VERDEF 0x6ffffffc
|
||||
#endif
|
||||
#ifndef DT_VERDEFNUM
|
||||
#define DT_VERDEFNUM 0x6ffffffd
|
||||
#endif
|
||||
#ifndef DT_VERNEED
|
||||
#define DT_VERNEED 0x6ffffffe
|
||||
#endif
|
||||
#ifndef DT_VERNEEDNUM
|
||||
#define DT_VERNEEDNUM 0x6fffffff
|
||||
#endif
|
||||
#ifndef DT_FLAGS
|
||||
#define DT_FLAGS 30
|
||||
#endif
|
||||
#ifndef DF_SYMBOLIC
|
||||
#define DF_SYMBOLIC 0x00000002
|
||||
#endif
|
||||
#ifndef DF_TEXTREL
|
||||
#define DF_TEXTREL 0x00000004
|
||||
#endif
|
||||
|
||||
namespace Elf {
|
||||
|
||||
/**
|
||||
* Define a few basic Elf Types
|
||||
*/
|
||||
typedef Elf_(Phdr) Phdr;
|
||||
typedef Elf_(Dyn) Dyn;
|
||||
typedef Elf_(Sym) Sym;
|
||||
typedef Elf_(Addr) Addr;
|
||||
typedef Elf_(Word) Word;
|
||||
|
||||
/**
|
||||
* Helper class around the standard Elf header struct
|
||||
*/
|
||||
struct Ehdr: public Elf_(Ehdr)
|
||||
{
|
||||
/**
|
||||
* Equivalent to reinterpret_cast<const Ehdr *>(buf), but additionally
|
||||
* checking that this is indeed an Elf header and that the Elf type
|
||||
* corresponds to that of the system
|
||||
*/
|
||||
static const Ehdr *validate(const void *buf);
|
||||
};
|
||||
|
||||
/**
|
||||
* Elf String table
|
||||
*/
|
||||
class Strtab: public UnsizedArray<const char>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Returns the string at the given index in the table
|
||||
*/
|
||||
const char *GetStringAt(off_t index) const
|
||||
{
|
||||
return &UnsizedArray<const char>::operator[](index);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper class around Elf relocation.
|
||||
*/
|
||||
struct Rel: public Elf_(Rel)
|
||||
{
|
||||
/**
|
||||
* Returns the addend for the relocation, which is the value stored
|
||||
* at r_offset.
|
||||
*/
|
||||
Addr GetAddend(void *base) const
|
||||
{
|
||||
return *(reinterpret_cast<const Addr *>(
|
||||
reinterpret_cast<const char *>(base) + r_offset));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper class around Elf relocation with addend.
|
||||
*/
|
||||
struct Rela: public Elf_(Rela)
|
||||
{
|
||||
/**
|
||||
* Returns the addend for the relocation.
|
||||
*/
|
||||
Addr GetAddend(void *base) const
|
||||
{
|
||||
return r_addend;
|
||||
}
|
||||
};
|
||||
|
||||
} /* namespace Elf */
|
||||
#include "Elfxx.h"
|
||||
|
||||
class Mappable;
|
||||
|
||||
|
@ -92,6 +92,26 @@ __wrap_dladdr(void *addr, Dl_info *info)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
__wrap_dl_iterate_phdr(dl_phdr_cb callback, void *data)
|
||||
{
|
||||
if (ElfLoader::Singleton.dbg == NULL)
|
||||
return -1;
|
||||
|
||||
for (ElfLoader::r_debug::iterator it = ElfLoader::Singleton.dbg->begin();
|
||||
it < ElfLoader::Singleton.dbg->end(); ++it) {
|
||||
dl_phdr_info info;
|
||||
info.dlpi_addr = reinterpret_cast<Elf::Addr>(it->l_addr);
|
||||
info.dlpi_name = it->l_name;
|
||||
info.dlpi_phdr = NULL;
|
||||
info.dlpi_phnum = 0;
|
||||
int ret = callback(&info, sizeof(dl_phdr_info), data);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
/**
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <signal.h>
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "Zip.h"
|
||||
#include "Elfxx.h"
|
||||
|
||||
/**
|
||||
* dlfcn.h replacement functions
|
||||
@ -33,6 +34,16 @@ extern "C" {
|
||||
sighandler_t __wrap_signal(int signum, sighandler_t handler);
|
||||
int __wrap_sigaction(int signum, const struct sigaction *act,
|
||||
struct sigaction *oldact);
|
||||
|
||||
struct dl_phdr_info {
|
||||
Elf::Addr dlpi_addr;
|
||||
const char *dlpi_name;
|
||||
const Elf::Phdr *dlpi_phdr;
|
||||
Elf::Half dlpi_phnum;
|
||||
};
|
||||
|
||||
typedef int (*dl_phdr_cb)(struct dl_phdr_info *, size_t, void *);
|
||||
int __wrap_dl_iterate_phdr(dl_phdr_cb callback, void *data);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -356,6 +367,8 @@ private:
|
||||
/* Keep track of Zips used for library loading */
|
||||
ZipCollection zips;
|
||||
|
||||
/* Forward declaration, see further below */
|
||||
class r_debug;
|
||||
public:
|
||||
/* Loaded object descriptor for the debugger interface below*/
|
||||
struct link_map {
|
||||
@ -365,6 +378,9 @@ public:
|
||||
const char *l_name;
|
||||
/* Address of the PT_DYNAMIC segment. */
|
||||
const void *l_ld;
|
||||
|
||||
private:
|
||||
friend class ElfLoader::r_debug;
|
||||
/* Double linked list of loaded objects. */
|
||||
link_map *l_next, *l_prev;
|
||||
};
|
||||
@ -381,6 +397,45 @@ private:
|
||||
/* Make the debugger aware of the unloading of an object */
|
||||
void Remove(link_map *map);
|
||||
|
||||
/* Iterates over all link_maps */
|
||||
class iterator
|
||||
{
|
||||
public:
|
||||
const link_map *operator ->() const
|
||||
{
|
||||
return item;
|
||||
}
|
||||
|
||||
const link_map &operator ++()
|
||||
{
|
||||
item = item->l_next;
|
||||
return *item;
|
||||
}
|
||||
|
||||
bool operator<(const iterator &other) const
|
||||
{
|
||||
if (other.item == NULL)
|
||||
return item ? true : false;
|
||||
MOZ_NOT_REACHED("r_debug::iterator::operator< called with something else than r_debug::end()");
|
||||
}
|
||||
protected:
|
||||
friend class r_debug;
|
||||
iterator(const link_map *item): item(item) { }
|
||||
|
||||
private:
|
||||
const link_map *item;
|
||||
};
|
||||
|
||||
iterator begin() const
|
||||
{
|
||||
return iterator(r_map);
|
||||
}
|
||||
|
||||
iterator end() const
|
||||
{
|
||||
return iterator(NULL);
|
||||
}
|
||||
|
||||
private:
|
||||
/* Version number of the protocol. */
|
||||
int r_version;
|
||||
@ -401,6 +456,7 @@ private:
|
||||
RT_DELETE /* Beginning to remove an object */
|
||||
} r_state;
|
||||
};
|
||||
friend int __wrap_dl_iterate_phdr(dl_phdr_cb callback, void *data);
|
||||
r_debug *dbg;
|
||||
|
||||
/**
|
||||
|
236
mozglue/linker/Elfxx.h
Normal file
236
mozglue/linker/Elfxx.h
Normal file
@ -0,0 +1,236 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef Elfxx_h
|
||||
#define Elfxx_h
|
||||
|
||||
/**
|
||||
* Android system headers have two different elf.h file. The one under linux/
|
||||
* is the most complete.
|
||||
*/
|
||||
#ifdef ANDROID
|
||||
#include <linux/elf.h>
|
||||
#else
|
||||
#include <elf.h>
|
||||
#endif
|
||||
#include <endian.h>
|
||||
|
||||
/**
|
||||
* Generic ELF macros for the target system
|
||||
*/
|
||||
#ifdef HAVE_64BIT_OS
|
||||
#define Elf_(type) Elf64_ ## type
|
||||
#define ELFCLASS ELFCLASS64
|
||||
#define ELF_R_TYPE ELF64_R_TYPE
|
||||
#define ELF_R_SYM ELF64_R_SYM
|
||||
#ifndef ELF_ST_BIND
|
||||
#define ELF_ST_BIND ELF64_ST_BIND
|
||||
#endif
|
||||
#define PRIxAddr "lx"
|
||||
#else
|
||||
#define Elf_(type) Elf32_ ## type
|
||||
#define ELFCLASS ELFCLASS32
|
||||
#define ELF_R_TYPE ELF32_R_TYPE
|
||||
#define ELF_R_SYM ELF32_R_SYM
|
||||
#ifndef ELF_ST_BIND
|
||||
#define ELF_ST_BIND ELF32_ST_BIND
|
||||
#endif
|
||||
#define PRIxAddr "x"
|
||||
#endif
|
||||
|
||||
#ifndef __BYTE_ORDER
|
||||
#error Cannot find endianness
|
||||
#endif
|
||||
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
#define ELFDATA ELFDATA2LSB
|
||||
#elif __BYTE_ORDER == __BIG_ENDIAN
|
||||
#define ELFDATA ELFDATA2MSB
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
#define ELFOSABI ELFOSABI_LINUX
|
||||
#ifdef EI_ABIVERSION
|
||||
#define ELFABIVERSION 0
|
||||
#endif
|
||||
#else
|
||||
#error Unknown ELF OSABI
|
||||
#endif
|
||||
|
||||
#if defined(__i386__)
|
||||
#define ELFMACHINE EM_386
|
||||
|
||||
// Doing this way probably doesn't scale to other architectures
|
||||
#define R_ABS R_386_32
|
||||
#define R_GLOB_DAT R_386_GLOB_DAT
|
||||
#define R_JMP_SLOT R_386_JMP_SLOT
|
||||
#define R_RELATIVE R_386_RELATIVE
|
||||
#define RELOC(n) DT_REL ## n
|
||||
#define UNSUPPORTED_RELOC(n) DT_RELA ## n
|
||||
#define STR_RELOC(n) "DT_REL" # n
|
||||
#define Reloc Rel
|
||||
|
||||
#elif defined(__x86_64__)
|
||||
#define ELFMACHINE EM_X86_64
|
||||
|
||||
#define R_ABS R_X86_64_64
|
||||
#define R_GLOB_DAT R_X86_64_GLOB_DAT
|
||||
#define R_JMP_SLOT R_X86_64_JUMP_SLOT
|
||||
#define R_RELATIVE R_X86_64_RELATIVE
|
||||
#define RELOC(n) DT_RELA ## n
|
||||
#define UNSUPPORTED_RELOC(n) DT_REL ## n
|
||||
#define STR_RELOC(n) "DT_RELA" # n
|
||||
#define Reloc Rela
|
||||
|
||||
#elif defined(__arm__)
|
||||
#define ELFMACHINE EM_ARM
|
||||
|
||||
#ifndef R_ARM_ABS32
|
||||
#define R_ARM_ABS32 2
|
||||
#endif
|
||||
#ifndef R_ARM_GLOB_DAT
|
||||
#define R_ARM_GLOB_DAT 21
|
||||
#endif
|
||||
#ifndef R_ARM_JUMP_SLOT
|
||||
#define R_ARM_JUMP_SLOT 22
|
||||
#endif
|
||||
#ifndef R_ARM_RELATIVE
|
||||
#define R_ARM_RELATIVE 23
|
||||
#endif
|
||||
|
||||
#define R_ABS R_ARM_ABS32
|
||||
#define R_GLOB_DAT R_ARM_GLOB_DAT
|
||||
#define R_JMP_SLOT R_ARM_JUMP_SLOT
|
||||
#define R_RELATIVE R_ARM_RELATIVE
|
||||
#define RELOC(n) DT_REL ## n
|
||||
#define UNSUPPORTED_RELOC(n) DT_RELA ## n
|
||||
#define STR_RELOC(n) "DT_REL" # n
|
||||
#define Reloc Rel
|
||||
|
||||
#else
|
||||
#error Unknown ELF machine type
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Android system headers don't have all definitions
|
||||
*/
|
||||
#ifndef STN_UNDEF
|
||||
#define STN_UNDEF 0
|
||||
#endif
|
||||
#ifndef DT_INIT_ARRAY
|
||||
#define DT_INIT_ARRAY 25
|
||||
#endif
|
||||
#ifndef DT_FINI_ARRAY
|
||||
#define DT_FINI_ARRAY 26
|
||||
#endif
|
||||
#ifndef DT_INIT_ARRAYSZ
|
||||
#define DT_INIT_ARRAYSZ 27
|
||||
#endif
|
||||
#ifndef DT_FINI_ARRAYSZ
|
||||
#define DT_FINI_ARRAYSZ 28
|
||||
#endif
|
||||
#ifndef DT_RELACOUNT
|
||||
#define DT_RELACOUNT 0x6ffffff9
|
||||
#endif
|
||||
#ifndef DT_RELCOUNT
|
||||
#define DT_RELCOUNT 0x6ffffffa
|
||||
#endif
|
||||
#ifndef DT_VERSYM
|
||||
#define DT_VERSYM 0x6ffffff0
|
||||
#endif
|
||||
#ifndef DT_VERDEF
|
||||
#define DT_VERDEF 0x6ffffffc
|
||||
#endif
|
||||
#ifndef DT_VERDEFNUM
|
||||
#define DT_VERDEFNUM 0x6ffffffd
|
||||
#endif
|
||||
#ifndef DT_VERNEED
|
||||
#define DT_VERNEED 0x6ffffffe
|
||||
#endif
|
||||
#ifndef DT_VERNEEDNUM
|
||||
#define DT_VERNEEDNUM 0x6fffffff
|
||||
#endif
|
||||
#ifndef DT_FLAGS
|
||||
#define DT_FLAGS 30
|
||||
#endif
|
||||
#ifndef DF_SYMBOLIC
|
||||
#define DF_SYMBOLIC 0x00000002
|
||||
#endif
|
||||
#ifndef DF_TEXTREL
|
||||
#define DF_TEXTREL 0x00000004
|
||||
#endif
|
||||
|
||||
namespace Elf {
|
||||
|
||||
/**
|
||||
* Define a few basic Elf Types
|
||||
*/
|
||||
typedef Elf_(Phdr) Phdr;
|
||||
typedef Elf_(Dyn) Dyn;
|
||||
typedef Elf_(Sym) Sym;
|
||||
typedef Elf_(Addr) Addr;
|
||||
typedef Elf_(Word) Word;
|
||||
typedef Elf_(Half) Half;
|
||||
|
||||
/**
|
||||
* Helper class around the standard Elf header struct
|
||||
*/
|
||||
struct Ehdr: public Elf_(Ehdr)
|
||||
{
|
||||
/**
|
||||
* Equivalent to reinterpret_cast<const Ehdr *>(buf), but additionally
|
||||
* checking that this is indeed an Elf header and that the Elf type
|
||||
* corresponds to that of the system
|
||||
*/
|
||||
static const Ehdr *validate(const void *buf);
|
||||
};
|
||||
|
||||
/**
|
||||
* Elf String table
|
||||
*/
|
||||
class Strtab: public UnsizedArray<const char>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Returns the string at the given index in the table
|
||||
*/
|
||||
const char *GetStringAt(off_t index) const
|
||||
{
|
||||
return &UnsizedArray<const char>::operator[](index);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper class around Elf relocation.
|
||||
*/
|
||||
struct Rel: public Elf_(Rel)
|
||||
{
|
||||
/**
|
||||
* Returns the addend for the relocation, which is the value stored
|
||||
* at r_offset.
|
||||
*/
|
||||
Addr GetAddend(void *base) const
|
||||
{
|
||||
return *(reinterpret_cast<const Addr *>(
|
||||
reinterpret_cast<const char *>(base) + r_offset));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper class around Elf relocation with addend.
|
||||
*/
|
||||
struct Rela: public Elf_(Rela)
|
||||
{
|
||||
/**
|
||||
* Returns the addend for the relocation.
|
||||
*/
|
||||
Addr GetAddend(void *base) const
|
||||
{
|
||||
return r_addend;
|
||||
}
|
||||
};
|
||||
|
||||
} /* namespace Elf */
|
||||
|
||||
#endif /* Elfxx_h */
|
Loading…
Reference in New Issue
Block a user